﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>The Node Beginner Book (Korean version) » A comprehensive Node.js tutorial</title>
        <meta name="description" content="A comprehensive Node.js tutorial for beginners (Korean version): Learn how to build a full blown web application with server-side JavaScript" />

        <link rel="stylesheet" type="text/css" href="default.css" />
        
        <script type="text/javascript">
            // Google Analytics
            var _gaq = _gaq || [];
            _gaq.push(['_setAccount', 'UA-2127388-6']);
            _gaq.push(['_trackPageview']);

            (function() {
                var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
                ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
                var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
            })();

            // Disqus
            var disqus_shortname = 'nodebeginner';
            var disqus_identifier = 'nodebeginner-book';
            var disqus_url = 'http://www.nodebeginner.org/index-kr.html';
            (function() {
                var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
                dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
                (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
            })();
        </script>
    </head>
    <body>
        <img style="display: none;" src="the_node_beginner_book_cover_medium.png" height="256" width="171" />
        <div id="forkmeongithub">
            <a href="https://github.com/ManuelKiessling/NodeBeginnerBook"><img src="fork_me_on_github.png" width="149" height="149" alt="Fork me on GitHub" /></a>
        </div>

        <div id="translations">
            <table>
                <tr>
                    <td>
                        <a href="index-jp.html">
                            <div class="flag"><img src="jp-flag.png" width="24" height="24" alt="japanese flag" /></div>
                            <div class="text">日本語で読む</div>
                        </a>
                    </td>
                    <td>
                        <a href="index-es.html">
                            <div class="flag"><img src="es-flag.png" width="24" height="24" alt="spanish flag" /></div>
                            <div class="text">Lee este tutorial en Español</div>
                        </a>
                    </td>
                    <td>
                        <a href="./">
                            <div class="flag"><img src="us-flag.png" width="24" height="24" alt="usa flag" /></div>
                            <div class="text">Read this tutorial in english</div>
                        </a>
                    </td>
                </tr>
                <tr>
                    <td>
                        <a href="index-zh-cn.html">
                            <div class="flag"><img src="cn-flag.png" width="24" height="24" alt="chinese flag" /></div>
                            <div class="text">阅读本书中文版</div>
                        </a>
                    </td>
                    <td>
                        <a href="index-zh-tw.html">
                            <div class="flag"><img src="tw-flag.png" width="24" height="24" alt="traditional chinese flag" /></div>
                            <div class="text">閱讀本書繁體中文版</div>
                        </a>
                    </td>
                    <td>
                        <a href="http://www.nodebeginner.ru">
                            <div class="flag"><img src="ru-flag.png" width="24" height="24" alt="russian flag" /></div>
                            <div class="text">Читать этот учебник на русском</div>
                        </a>
                    </td>
                </tr>
            </table>
        </div>

        <div class="buybox">
            <div class="buy-the-bundle">
                <div class="cover">
                    <p>
                        The perfect introduction plus the perfect reference in one bundle!
                    </p>
                    <a href="buy-bundle/index.html"><img src="the_node_beginner_book_cover_small.png" height="86" width="57" /></a>
                    <a href="buy-bundle/index.html"><img src="hands-on_node.js_cover.png" height="86" width="57" /></a>
                </div>
                <div class="description">
                    <p>
                        LeanBundle currently offers<br />
                        the final version of
                        <br />
                        <strong>The Node Beginner Book</strong>
                        <br />
                        plus Pedro Teixeira's excellent
                        <br />
                        <strong>Hands-on Node.js</strong> for only
                        <br />
                        <br />
                        <strong class="price dollarsign">$</strong><strong class="price">9.99</strong>
                        <br />
                        (regular price <del>$21.98</del>)
                    </p>
                </div>
                <div class="buy">
                    <p>
                        226 pages in total
                        <br />
                        PDF, ePub & MOBI
                        <br />
                        Direct download
                        <br />
                        Free updates
                    </p>
                    <a class="buttonlink" href="buy-bundle/index.html">
                        <div class="button">Buy this<br />bundle now</div>
                    </a>
                </div>
            </div>
        </div>

        <div id="book">
        <h1>The Node Beginner Book</h1>

        <div id="author">A Node.js tutorial by <a href="http://twitter.com/manuelkiessling">Manuel Kiessling</a><br/>
                                   translated into korean by <a href="http://facebook.com/stoneshim">심형석</a>, <a href="http://blog.doortts.com/">채수원</a></div>

        <a name="about"></a>

        <h2>이 문서에 대하여</h2>

        <p>
            본 문서의 목표는 Node.js용 애플리케이션 개발을 시작을 할 수 
            있게 만드는 것입니다. 그리고 함께 알아야 하는 “고급” 
            JavaScript에 관한 모든 것을 다룹니다. 본 문서는 전형적인 
            “Hello World” 튜토리얼 보다는 더 많이 다룹니다.
        </p>

        <a name="status"></a>

        <h3>상태</h3>

        <p>
            당신은 현재 이 책의 최종버전을 읽고 있습니다. 즉, 새로운
            버전의 Node.js에 있는 변경사항들을 반영하거나 오류를 수정할 
            때만 업데이트 합니다.
        </p>

        <p>
            이 책에 있는 코드 예제들은 Node.js 0.6.11에서 동작하는지 
            테스트 되었습니다.
        </p>

        <a name="intended-audience"></a>

        <h3>대상 독자</h3>

        <p>
            이 문서는 저와 비슷한 배경을 가진 독자들에게 가장 잘 맞을 겁니다. 
            적어도 객체지향 언어 –루비, 파이선, PHP, 혹은 자바 같은 언어- 하나
            정도에는 경험이 있고, JavaScript에는 약간의 경험만 있으며, 
            Node.js는 이번이 처음인 분들 말입니다.
        </p>

        <p>
            이미 다른 언어에 대한 경험을 가진 개발자들을 대상으로 한다는 말은 
            데이터 타입이나 변수, 제어구조 같은 것들을 이 문서에서 다루지 않다는
            뜻입니다. 본 문서를 이해하기 위해서는 그런 기본적인 것들은 미리 알고
            있어야 합니다.
        </p>

        <p>
            하지만, JavaScript에서의 객체나 함수들은 다른 대부분의 언어들에 
            대응되는 것과 다르기 때문에, 좀 더 자세히 설명하겠습니다.
        </p>

        <a name="structure"></a>

        <h3>이 문서의 구조</h3>

        <p>
            이 문서를 마치는 시점에, 유저들에게 웹페이지를 보여주고 파일들을 
            업로드 할 수 있는 완성된 웹 애플리케이션을 가지게 될 것입니다. 
        </p>

        <p>
            이 유스케이스를 만족하기 위해 “충분한 정도”까지만 코드를 만드는 
            것에서 조금 더 나아가서, “세상을 바꾸는 정도”는 아닙니다만, 
            간결하지만 완결성있는 프레임워크를 만들어서 우리의 애플리케이션의 
            다른 부분들로부터 깔끔하게 분리할 겁니다.
        </p>

        <p>
            우리는 Node.js에서 JavaScript 개발을 하는 것이 브라우저에서 
            JavaScript를 개발하는 것과 어떻게 다른지를 살펴보는 것으로 
            시작하려 할겁니다.
        </p>

        <p>
            다음으로, “Hello World” 애플리케이션을 작성하는 훌륭한 오랜 전통을 
            따를 생각입니다. 그리고 그건 “무언가를 하는” 아주 기본이 되는 
            Node.js  애플리케이션이 될 겁니다.
        </p>

        <p>
            그리고 나서는, 우리가 만들기 원하는 “실제” 애플리케이션의 종류가 
            무엇인지에 대해 논의하고, 이 애플리케이션을 조립하기 위해 구현해야 
            하는 다른 부분들을 자세히 살펴보고, 하나씩 이 각각의 부분들에 대해 
            작업을 시작할 생각입니다.
        </p>

        <p>
            약속드렸듯이, 우리는 JavaScript의 고급 개념 몇 가지와,  그것을 
            어떻게 사용하는지, 그리고 우리가 아는 다른 프로그래밍 언어의 개념과 
            이 개념이 어떻게 다른지 살펴볼 것입니다.
        </p>

        <p>
            완성된 애플리케이션의 소스코드는 아래 링크를 통해 다운 받으실 수 
            있습니다.
            <a href="https://github.com/ManuelKiessling/NodeBeginnerBook/tree/master/code/application">
            the NodeBeginnerBook Github repository</a>.
        </p>

        <div id="table-of-contents-headline">차례</div>
        <div id="table-of-contents">
            <ul>

                <li><a href="#about">이 문서에 대하여</a>
                    <ul>
                        <li><a href="#status">상태</a></li>
                        <li><a href="#intended-audience">대상 독자</a></li>
                        <li><a href="#structure">이 문서의 구조</a></li>
                    </ul>
                </li>

                <li><a href="#javascript-and-nodejs">JavaScript와 Node.js</a>
                    <ul>
                        <li><a href="#javascript-and-you">JavaScript와 당신</a></li>
                        <li><a href="#a-word-of-warning">주의 사항</a></li>
                        <li><a href="#server-side-javascript">서버사이드 JavaScript</a></li>
                        <li><a href="#hello-world">"Hello World"</a></li>

                    </ul>
                </li>
                <li><a href="#a-full-blown-web-application-with-nodejs">Node.js로 활짝 핀 웹 애플리케이션</a>
                    <ul>
                        <li><a href="#the-use-cases">유스케이스</a></li>
                        <li><a href="#the-application-stack">애플리케이션 스택</a></li>
                    </ul>

                </li>
                <li><a href="#building-the-application-stack">애플리케이션 스택 구축하기</a>
                    <ul>
                        <li><a href="#a-basic-http-server">기본 HTTP 서버</a></li>
                        <li><a href="#analyzing-our-http-server">우리의 HTTP 서버를 분석하기</a></li>
                        <li><a href="#passing-functions-around">함수를 전달하기</a></li>
                        <li><a href="#how-function-passing-makes-our-http-server-work">어떻게 함수 전달이 
                            HTTP 서버를 동작하게 하는가</a></li>

                        <li><a href="#event-driven-callbacks">Event-driven callbacks</a></li>
                        <li><a href="#how-our-server-handles-requests">우리 서버는 요청을 어떻게 처리하는가?</a></li>
                        <li><a href="#finding-a-place-for-our-server-module">server 모듈의 위치 잡기</a>
                        </li>
                        <li><a href="#whats-needed-to-route-requests">요청을 "route" 하려면?</a></li>
                        <li><a href="#execution-in-the-kongdom-of-verbs">동사들(verbs)의 나라에서의 실행(execution)</a></li>
                        <li><a href="#routing-to-real-request-handlers">실제 request handler로 라우팅(routing)하기</a></li>

                        <li><a href="#making-the-request-handlers-respond">request handler가 응답하게 만들기</a>
                            <ul>
                                <li><a href="#how-to-not-do-it">해서는 안되는 것</a></li>
                                <li><a href="#blocking-and-non-blocking">Blocking 과 non-blocking</a></li>
                                <li><a href="#responding-request-handlers-with-non-blocking-operations">request handler가
                                    non-blocking 방식으로 동작하면서 응답하기</a>
                                </li>
                            </ul>

                        </li>
                        <li><a href="#serving-something-useful">유용한 것을 제공하기</a>
                            <ul>
                                <li><a href="#handling-post-requests">POST 요청 처리하기</a></li>
                                <li><a href="#handling-file-uploads">파일 업로드 처리하기</a></li>
                            </ul>
                        </li>

                        <li><a href="#conclusion-and-outlook">결론과 개관</a></li>
                    </ul>
                </li>
            </ul>
        </div>

        <a name="javascript-and-nodejs"></a>

        <h2>JavaScript와 Node.js</h2>

        <a name="javascript-and-you"></a>

        <h3>JavaScript와 당신</h3>

        <p>
            기술적인 부분들에 대해 이야기 하기 앞서, 잠깐 짬을 내서 당신과 
            JavaScript와의 관계에 대해 이야기 해 봅시다. 이번 챕터를 읽고 
            나면 이 문서를 계속 읽어야 할지 판단할 수 있을 겁니다.
        </p>

        <p>
            만약 당신이 나와 같다면, 당신은 오래 전에 HTML 문서 작성을 계기로 
            HTML “개발”을 시작했습니다. 당신은 이 재밌는 일을 JavaScript와 
            함께 했습니다. 하지만 매우 기초적인 방식으로 사용했죠. 웹페이지 
            이곳 저곳에 상호작용 기능을 추가하는 식으로 말입니다.
        </p>

        <p>
            당신이 정말 원했던 것은 “실제의 것”이었습니다. 당신은 어떻게 하면 
            복잡한 웹 사이트를 만들 수 있는지 알고 싶었습니다. 그래서 PHP나 
            루비, 자바 같은 프로그래밍 언어를 배웠고, “백엔드”코드를 작성하기 
            시작했습니다.
        </p>

        <p>
            그러면서도, JavaScript에 눈은 계속 두고 있었죠. jQuery나 
            Prototype같은 것들의 소개를 보면서 말입니다. 그것들은 JavaScript 
            영토내에서 좀 더 진보해나갔습니다. 그러면서 JavaScript가 실제로는 
            <em>window.open()</em> 함수 이상이라는 것을 보았습니다.
        </p>

        <p>
            하지만, 여전히 이 언어는 프론트앤드에 머물러 있었고, 웹페이지를 
            꾸미고 싶을 때 마음대로 다룰 수 있는 jQuery가 있다는 것이 좋긴 
            했지만, 결국 당신은 JavaScript <em>사용자</em>였을 뿐입니다. 
            결코 JavaScript <em>개발자</em>는 아니었죠.
        </p>

        <p>
            그러다 서버 위에서 동작하는 JavaScript, Node.js가 나왔습니다. 
            너무 멋지지 않습니까?
        </p>

        <p>
            이제 비로소 오래되었지만 새로운 JavaScript를 살펴봐야 할 
            시기라고 마음먹습니다. 하지만 잠시만요. Node.js 애플리케이션을 
            작성하는 것과 왜 그런 방식으로 작성해야만 하는 것인지, 즉 
            Javascript를 이해하는 것은 다른 이야기 입니다. 
        </p>

        <p>
            문제는 이렇습니다. JavaScript는 두 개, 혹은 세 개의 
            삶(90년대 중반부터 시작된 작고 우스운 DHTML 헬퍼, jQuery나 그 
            비슷한 종류의 좀 더 진지한 프론트앤드 도구, 그리고 지금은 
            서버사이드)을 살았기 때문에 JavaScript를 “올바른” 방식으로 
            배우는 것을 도와줄 정보를 찾는 것이 쉽지는 않습니다.JavaScript를 
            단순히 사용하는 것이 아니라, 개발하고 있다는 느낄 수 있도록 
            Node.js 애플리케이션을 작성하기 위해서 말입니다. 
        </p>

        <p>
            바로 그겁니다. 당신은 이미 경험있는 개발자이고, 여기저기 해킹하듯 
            새로운 기술을 배우고 나서 엉뚱하게 사용하는 것을 원하지 않습니다. 
            당신은 올바른 각도로 이것에 접근하고 있다는 것을 확신하고 싶을 
            겁니다.
        </p>

        <p>
            물론, 훌륭한 문서들이 널려 있습니다. 하지만 때로는 문서만으로는 
            충분하지 않습니다. 필요한 것은 바로 올바른 안내입니다.
        </p>

        <p>
            저의 목표가 당신에게 그런 가이드를 제공하는 것입니다.
        </p>

        <a name="a-word-of-warning"></a>

        <h3>주의 사항</h3>

        <p>
            정말 뛰어난 JavaScript 개발자들이 있습니다. 저는 그런 사람이 아닙니다.
        </p>

        <p>
            저는 단지 앞에서 말했던 그런 수준의 사람입니다. 저는 백앤드 웹 
            애플리케이션 개발에 관해 한 두 개쯤은 알고 있습니다만, 여전히 
            “진정한” JavaScript에 대해서는 신참이고, Node.js에 대해서는 
            마찬가지입니다. JavaScript의 좀 더 고급스러운 내용에 대해서는 
            최근에서야 배웠습니다. 경험 많은 사람이 아니죠.
        </p>

        <p>
            그게 바로 이 책에 “초보에서 전문가로”의 책이 아닌 이유입니다. 
            그 보다는 “아주 초보에서 발전된 초보로”에 더 가까운 책입니다.
        </p>

        <p>
            제가 실패하지 않는다면, 이 책은 제가 Node.js를 시작할 때 가지고
            있었다면 좋았겠다 싶은 생각이 드는 그런 종류의 문서가 될 것입니다.
        </p>

        <a name="server-side-javascript"></a>

        <h3>서버 사이드 JavaScript</h3>

        <p>
            첫 번째 JavaScript의 구현체는 브라우저안에 살았습니다. 하지만 
            단순히 환경에 불과했습니다. JavaScript로 무엇을 할 수 있는지 
            정의하였습니다만, 해당 언어 자체가 할 수 있는 것이 무엇인지에 
            대해서는 그다지 많이 알려주지 않았습니다. 
            JavaScript는 “완결성을 가진” 언어입니다. 당신은 이 언어를 수 많은 
            환경속에서 사용할 수 있고 다른 “완결성을 가진” 언어들과 마찬가지로 
            무엇이든지 만들어 낼 수 있습니다.
        </p>

        <p>
            Node.js는 실제로 단지 다른 환경일 뿐입니다. Node.js는 브라우저 밖, 
            백앤드에서 JavaScript를 실행할 수 있게 해줍니다.
        </p>

        <p>
            백앤드에서 당신이 지정한 JavaScript를 수행하기 위해서는, 잘 해석되고 
            실행되어야 합니다. Node.js가 하는 것이 바로 그 일입니다. 
            그리고 그 일은 구글 크롬 브라우저가 사용하는 JavaScript 실행환경과 
            동일한, 구글의 V8 가상머신을 사용해 이루어집니다.
        </p>

        <p>
            거기에 더해서, Node.js는 많은 유용한 모듈을 탑재하고 있습니다. 
            그렇기 때문에 string을 console로 뿌리는 것 같은 것을 바닥부터 
            모두 작성할 필요가 없습니다. 
        </p>

        <p>
            요컨대, Node.js는 서버사이드 JavaScript 실행환경과 라이브러리, 
            이렇게 두 가지로 이루어져 있습니다.
        </p>

        <p>
            이것들을 사용하기 위해서는 Node.js를 설치해야 합니다. 
            <a href="https://github.com/joyent/node/wiki/Installation" title="Building and Installing Node.js">
            공식 설치 안내 사이트</a>를 
            방문해서 설치를 마친 다음에 다시 오시길 정중히 권합니다. 
        </p>

        <a name="hello-world"></a>

        <h3>"Hello World"</h3>

        <p>
            좋습니다. 바로 차가운 물로 뛰어들어보죠. 
            우리의 첫 번째 Node.js 애플리케이션, “Hello World”를 작성해 봅시다.
        </p>

        <p>
            즐겨쓰는 에디터를 실행해서 <em>helloworld.js</em>라는 파일을 
            만드세요. STDOUT(표준출력)으로 “Hello World” 문자열을 출력할 
            생각입니다. 
            그 일을 하는 코드는 다음과 같습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="pln">console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span></pre>
        <p>
            파일을 저장하고 Node.js를 통해서 실행해 보겠습니다.
        </p>

        <pre>node helloworld.js</pre>
        <p>
            터미널에 <em>Hello World</em>라고 출력될 겁니다.
        </p>

        <p>
            좋아요! 조금 심심하죠? 좀 더 리얼한 걸 만들어 봅시다.
        </p>


        <a name="a-full-blown-web-application-with-nodejs"></a>

        <h2>Node.js로 활짝 핀 웹 애플리케이션</h2>

        <a name="the-use-cases"></a>

        <h3>유스케이스</h3>

        <p>
            간단하지만 리얼하게 해 봅시다.
        </p>
        <ul>

            <li>
                사용자는 웹 브라우저로 우리의 웹 애플리케이션을 이용할 수 있다.
            </li>
            <li>
                사용자가 http://<em>domain</em>/start를 요청하면 파일 업로드 
                폼이 들어있는 웰컴페이지를 볼 수 있어야 한다. 
            </li>
            <li>
                업로드할 이미지 파일을 선택해서 폼으로 전송하면, 
                해당 이미지는 http://<em>domain</em>/upload로 업로드 되어야 
                하며, 업로드가 끝나면 해당 페이지에 표시된다.
            </li>

        </ul>
        <p>
            이 정도면 충분합니다. 이제, 당신은 구글링을 하고 코드를 좀 만지면 
            위  요구사항을 달성할 수 있습니다. 
            하지만 우리가 원하는 건 그게 아닙니다.
        </p>

        <p>
            더욱이, 우리가 원하는 것은 목표를 만족하는 가장 기초적인 코드를 
            작성하는 것이 아니라, 우아하고 적절한 코드를 만드는 것입니다. 
            우린 의도적으로 좀 더 추상화된 부분을 넣어서 좀 더 복잡한 Node.js 
            애플리케이션을 만들고 있다는 느낌을 갖게 해볼 예정입니다.
        </p>

        <a name="the-application-stack"></a>

        <h3>애플리케이션 스택</h3>

        <p>
            우리의 애플리케이션을 면밀하게 살펴봅시다. 유스케이스를 만족시키기 
            위해서 구현되어야 하는 부분은 어떤 부분인가요?
        </p>

        <ul>
            <li>
                우리는 웹페이지를 제공해야 한다. 따라서 
                <strong>HTTP 서버</strong>가 필요하다.
            </li>
            <li>
                우리는 서버는 어떤 URL 요청(request)을 받았는지에 따라 다르게 
                응답해야 한다. 따라서, 요청과 요청을 처리할 핸들러들을 연결짓기
                위한 <strong>라우터(router)</strong> 같은 것이 필요하다. 
            </li>
            <li>
                서버로 도착한 요청들, 그리고 라우터를 이용해서 라우팅된 요청들을 
                만족시키기 위해서 실제적인 
                <strong>요청 핸들러(request handlers)</strong>가 필요하다.
            </li>
            <li>
                라우터는 아마도 들어오는 어떠한 POST 데이터들도 다룰 수 있어야 
                한다. 그리고 해당 데이터를 다루기 편한 형태로 만들어 
                request handler 들에게 넘겨야 한다. 따라서 
                <strong>요청 데이터 핸들링(request data handling)</strong>이 
                필요하다.
            </li>
            <li>
                URL에 대한 요청을 다루는 것뿐 아니라 URL이 요청되었을 때 내용을 
                표시할 필요도 있다. 이 말은 즉, request handler 들이 
                사용자 브라우저로 콘텐트를 보내기 위해 사용할 수 있는 
                <strong>뷰 로직(view logic)</strong>이 필요하다는 이야기다.
            </li>
            <li>
                마지막이지만 중요한 것으로는, 사용자가 이미지들을 업로드 할 수 
                있어야 하니까, 세부 사항을 다루는 
                <strong>업로드 핸들링(upload handling)</strong>이 필요할 것이다.
            </li>
        </ul>

        <p>
            PHP를 이용해서 이런 스택을 구축하는 방법에 대해 잠시 생각해 보는 
            시간을 가져봅시다. 전형적으로 mod_php5를 가진 아파치 HTTP 서버를 
            설치하는 것을 생각해 볼 수 있습니다.
            <br>
            이것은 “웹페이지를 제공하고 HTTP 요청을 받을 수 있어야 한다”는 
            요구의 전체를 PHP만으로는 이룰 수가 없다는 것을 의미합니다.
        </p>

        <p>
            그런데 node의 경우는 조금 다릅니다. Node.js로는 우리는 
            애플리케이션뿐 아니라, HTTP 서버를 통째로 구현할 것이기 때문입니다. 
            사실 따지고보면, 우리의 웹 애플리케이션과 웹 서버는 기본적으로 
            동일합니다.
        </p>

        <p>
            해야 할 일이 많은 것처럼 들릴 수 있는데, 
            Node.js를 이용하면 그렇지 않다는 걸 바로 보게 될 것입니다.
        </p>

        <p>
            자 우리 애플리케이션 스택의 첫 번째 파트인 
            HTTP 서버 구현을 시작해 봅시다.
        </p>

        <a name="building-the-application-stack"></a>

        <h2>애플리케이션 스택 구축하기</h2>

        <a name="a-basic-http-server"></a>

        <h3>기본 HTTP 서버</h3>

        <p>
            “리얼한” Node.js 애플리케이션을 만들어야겠다고 생각했을 때, 
            어떻게 코드를 작성할지 뿐 아니라 어떻게 코드를 구조화 시킬지에 대해
            고민을 했습니다.
            <br>
            한 파일에 다 넣어야 하나? 웹에 있는 대부분의 튜터리얼들은 
            Node.js에서 하나의 기본 HTTP 서버에서 한 곳에 모든 로직을 갖도록 
            작성하는 법을 알려주었습니다. 
            내가 당장 구현하는 것보다 더 많은 것을 해야 할 때에도
            내 코드가 가독성이 좋으려면 어떻게 해야 할까요?
        </p>

        <p>
            관심사가 다른 코드들을 분리해서 모듈로 넣어 유지하는 것이 상대적으로
            쉬운 방법이라는 것을 알게 되었습니다.
        </p>

        <p>
            이렇게 하면 Node.js를 가지고 실행할 때 사용하는 main 파일을 깔끔하게
            유지할 수 있고, main 파일과 다른 파일에서 서로 가져다 사용하는 
            모듈들을 깔끔하게 유지할 수 있습니다.
        </p>

        <p>
            자 그럼 우리의 애플리케이션을 실행하는 데 쓸 main 파일과 HTTP 서버 
            코드가 거주하게 될 모듈 파일을 만들어 보겠습니다.
        </p>

        <p>
            제가 보기에는 main 파일의 꽤 표준적인 이름은 index.js 입니다. 
            서버 모듈을 <em>server.js</em>라는 파일로 만드는 것은 
            괜찮을 것 같습니다.
        </p>

         <p>
            자, 서버모듈을 만들어 봅시다. <em>server.js</em> 라는 파일을 
            프로젝트 루트 디렉토리에 만든 다음 아래 코드를 타이핑해 넣습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br>http</span><span
                class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="kwd">function</span><span
                class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">write</span><span
                class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">end</span><span
                class="pun">();</span><span class="pln"><br></span><span class="pun">}).</span><span
                class="pln">listen</span><span class="pun">(</span><span class="lit">8888</span><span
                class="pun">);</span></pre>

        <p>
            이게 끝입니다.  잘 동작하는 HTTP서버를 방금 만들었습니다. 
            실행해서 확인해 보겠습니다. 
            Node.js로 방금 만든 스크립트를 실행합니다.
        </p>
        <pre>node server.js</pre>
        <p>
            이제 브라우저를 열고 
            <a href="http://localhost:8888/" rel="nofollow">http://localhost:8888/</a> 
           로 접속합니다. “Hello World”가 찍히는 웹페이지가 보일 겁니다.
        </p>

        <p>
            매우 흥미롭습니다. 그렇죠? 지금은 여기서 무슨 일이 일어났는 지를 
            먼저 살펴봅시다. 프로젝트를 어떻게 구조화 하는 지에 대한 질문은 
            잠시 미루고, 뒤에서 다시 다루겠습니다. 
        </p>

        <a name="analyzing-our-http-server"></a>

        <h3>우리의 HTTP 서버를 분석하기</h3>

        <p>
            자, 그럼 실제로 뭐가 어떻게 된 건지 살펴봅시다.
        </p>

        <p>
            첫 줄은 Node.js에 기본으로 포함된 <em>http</em> 모듈을 읽어 들인 
            다음, http 라는 이름의 변수를 통해 접근할 수 있게 만들었습니다. 
        </p>

        <p>
            그 다음 http 모듈에서 제공하는 함수 중 하나인 
            <em>createServer</em>를 호출합니다. 해당 함수는 객체를 리턴하고, 
            그 리턴된 객체는 <em>listen</em> 이라는 이름의 함수를 가지고 
            있습니다. 이 listen 함수는 HTTP서버에서 요청대기할 포트 번호를 
            나타내는 숫자를 받습니다.
        </p>

        <p>
            <em>http.createServer</em>의 괄호 뒤에 나오는 함수 선언에 대해서는 
            잠시 무시합시다.
        </p>

        <p>
            다음과 같은 식으로 8888 port를 listen 하는 서버를 만들 수도 있습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">var</span><span
                class="pln"> server </span><span class="pun">=</span><span class="pln"> http</span><span
                class="pun">.</span><span class="pln">createServer</span><span class="pun">();</span><span
                class="pln"><br>server</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span></pre>

        <p>
            8888포트를 Listen 하는 HTTP 서버를 시작한 다음 아무일도 안 하는 
            코드입니다. 어떤 요청이 들어오더라도 말입니다. 
            테스트 해보면 웹 브라우저는 대기상태에 빠집니다.
        </p>

        <p>
            <em>createServer()</em> 호출의 첫 번째 파라미터가 있어야 하는 
            부분에 함수의 정의가 나온 부분이 매우 흥미롭습니다.(당신의 
            background가 php처럼 더 보수적인 언어라면 이상하게 보일 겁니다). 
        </p>

        <p>
            이 함수정의는 <em>createServer()</em>에 넘기는 첫 번째 파라미터입니다.
            JavaScript에서는 함수도 다른 값처럼 파라미터로 넘길 수 있습니다.
        </p>

        <a name="passing-functions-around"></a>

        <h3>함수를 전달하기</h3>

        <p>
            예를 들면 다음과 같은 것이 가능합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> say</span><span
                class="pun">(</span><span class="pln">word</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span
                class="pln">word</span><span class="pun">);</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> execute</span><span
                class="pun">(</span><span class="pln">someFunction</span><span class="pun">,</span><span class="pln"> value</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; someFunction</span><span
                class="pun">(</span><span class="pln">value</span><span class="pun">);</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>execute</span><span
                class="pun">(</span><span class="pln">say</span><span class="pun">,</span><span
                class="pln"> </span><span class="str">"Hello"</span><span class="pun">);</span></pre>

        <p>
            주의해서 보세요! 우리는 여기서 <em>say</em> 라는 함수를 
            <em>execute</em> 함수의 첫 번째 파라미터로 넘기고 있습니다. 
            <em>say</em>함수의 return 값을 넘기는 것이 아니라 
            <em>say</em> 그 자체를 넘기는 겁니다.
        </p>

        <p>
            따라서, <em>say</em>는 <em>execute</em> 함수 내에서 
            <em>someFunction</em> 이라는 변수가 되며 execute는 
            이 변수에 담긴 함수를 <em>someFunction()</em> 이라고 표시함으로써 
            호출할 수 있습니다.(변수에 괄호를 치면서)
        </p>

		<p>
            <em>say</em>는 한 개의 파라미터를 가지므로 <em>execute</em>는 
            <em>someFunction</em>을 호출하면서 파라미터를 넘길 수 있습니다.
        </p>


        <p>
            방금 한 것처럼 우리는 함수를 그 이름으로 다른 함수의 파라미터로 
            넘길 수 있습니다. 하지만 이렇게 먼저 정의하고 그것을 넘기는 간접적인 
            방법을 사용할 필요가 없습니다. 우리는 함수를 정의하면서 동시에
            다른 함수의 파라미터로 넘길 수 있습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> execute</span><span
                class="pun">(</span><span class="pln">someFunction</span><span class="pun">,</span><span class="pln"> value</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; someFunction</span><span
                class="pun">(</span><span class="pln">value</span><span class="pun">);</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>execute</span><span
                class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">word</span><span class="pun">){</span><span class="pln"> console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span
                class="pln">word</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">},</span><span class="pln"> </span><span class="str">"Hello"</span><span
                class="pun">);</span></pre>

        <p>
            우린 <em>execute</em>의 첫 번째 파라미터 위치에 
            <em>execute</em>에게 넘기려고 하는 함수를 정의했습니다.
        </p>

        <p>
            이때 우리는 함수 이름을 줄 필요가 없습니다. 
            이것이 바로 <em>anonymous function</em> 이라고 불리는 이유입니다. 
        </p>

        <p>
            이것으로 제가 “advanced” JavaScript 라고 부르고 싶은 것에 대해 
            처음으로 살짝 맛을 봤습니다. 이제 이것을 기억합시다. 
            JavaScript 에서는 우리는 함수를 다른 함수의 파라미터로 넘길 수 있다. 
            이것을 함수를 변수에 할당한 후에 넘길 수도 있고, 
            정의하는 동시에 넘길 수도 있다.
        </p>

        <a name="how-function-passing-makes-our-http-server-work"></a>

        <h3>어떻게 함수 전달이 HTTP 서버를 동작하게 하는가</h3>

		<p>
            우리의 미니멀리즘적인 HTTP 서버로 되돌아가 봅시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br>http</span><span
                class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="kwd">function</span><span
                class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">write</span><span
                class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">end</span><span
                class="pun">();</span><span class="pln"><br></span><span class="pun">}).</span><span
                class="pln">listen</span><span class="pun">(</span><span class="lit">8888</span><span
                class="pun">);</span></pre>

        <p>
            이제 위 코드가 어떤 일을 하는지 명확해집니다. anonymous 함수가 <em>createServer</em> 함수로 전달되었습니다. 
        </p>

        <p>
            위 코드를 리팩터링 하면 아래와 같이 만들 수 있습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">write</span><span
                class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
                class="pln"><br>&nbsp; response</span><span class="pun">.</span><span class="pln">end</span><span
                class="pun">();</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>http</span><span
                class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span></pre>

        <p>
            이제 다음과 같은 질문을 할 차례입니다.
        </p>

        <a name="event-driven-callbacks"></a>

        <h3>Event-driven callbacks</h3>

        <p>
            답은 a) 그리 쉽지 않고(최소한 저에게는), 
            b) Node.js가 동작하는 방식이 어떤가에 있습니다. 
            Node.js가 굉장히 빠른 이유가 바로 이벤트 드리븐 때문입니다.
        </p>

        <p>
            배경 설명을 위해 Felix Geisendörfer의 뛰어난 포스트 
            <a href="http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb">
            Understanding node.js</a>
           를 읽어 보시는 것도 좋을 것 같네요.
        </p>

        <p>
            이것은 모두 결국 Node.js가 이벤트 드리븐으로 동작한다는 사실로 
            귀결됩니다. 오, 저 역시 이것이 정확히 무슨 뜻인지 모릅니다. 
            하지만 Node.js로 웹 기반 애플리케이션을 만드는 우리들에게 이게 왜 
            의미가 있는지 한번 살펴봅시다.
        </p>

        <p>
            <em>http.createServer</em> 메소드를 호출할 때, 우리는 서버가 
            특정 포트를 listen 할 뿐 아니라 HTTP 요청이 올 때 
            뭔가를 하기를 기대합니다.
        </p>

        <p>
            문제는 이것(HTTP 요청)이 비동기적으로 일어난다는 점입니다.
            HTTP 요청은 언제든지 일어날 수 있지만 
            우리에게는 하나의 프로세스밖에 없습니다.
        </p>

        <p>
            PHP 애플리케이션을 만들때 우린 이런것은 신경 쓰지 않죠. 
            HTTP 요청이 올 때마다 웹서버(보통 Apache)가 이 요청을 위해 새 
            프로세스를 포크하고 해당하는 PHP 스크립트를 처음부터 끝까지 
            실행합니다.
        </p>

        <p>
            제어흐름의 관점에서 보면, 새로운 요청이 8888 포트로 들어왔을 때 
            Node.js의 제어 안에 있습니다.(역주: PHP의 경우 새로운 요청이 
            들어왔을때 제어흐름은 Apache에 있고, Apache가 알아서 처리하죠)
            이것을 도대체 어떻게 해결하죠?
        </p>

        <p>
            이것이 바로 Node.js/JavaScript의 이벤트 드리븐 디자인이 빛을 
            발하는 부분입니다. 다만 몇 가지 새로운 개념을 익히긴 해야합니다. 
            이 개념들을 우리 서버 코드에 어떻게 적용할지 한번 봅시다.
        </p>

        <p>
            서버를 생성할 때 서버 생성 메소드의 파라미터로 함수를 넘깁니다. 
            요청이 올 때마다 파라미터로 넘긴 함수가 호출됩니다.
        </p>

        <p>
            요청이 언제 발생할 지는 모르지만 이제 들어오는 요청을 처리할 곳 
            생겼습니다. 파라미터로 넘긴 함수입니다. 
            함수를 먼저 정의한 후 넘겼든 anonymous function으로 넘겼든 말이죠.
        </p>

        <p>
            이 개념을 <em>callback</em> 이라고 합니다. 
            우리는 메소드에 함수를 넘기고, 메소드는 관련된 이벤트가 발생하면 
            이 함수를 <em>거꾸로 호출(call back)</em> 합니다.
        </p>

        <p>
            최소한 저에게는 이것을 이해하는 데 좀 시간이 걸렸습니다. 
            확실히 이해가 되지 않으면 Felix의 블로그 포스트를 다시 읽어보세요.
        </p>

        <p>
            이 새로운 개념을 가지고 동작을 시켜 볼까요?
            서버를 생성한 후 아무런 HTTP 요청이 발생하지 않아서 우리가 넘긴 
            callback 함수도 호출되지 않고 있다면, 우리 코드가 동작한다는 것을 
            어떻게 알 수 있을까요? 아래와 같이 해 봅시다:
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request received."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>http</span><span class="pun">.</span><span class="pln">createServer</span><span
                class="pun">(</span><span class="pln">onRequest</span><span class="pun">).</span><span class="pln">listen</span><span
                class="pun">(</span><span class="lit">8888</span><span class="pun">);</span><span class="pln"><br><br>console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span></pre>

        <p>
            <em>onRequest</em> 함수 (callback)가 호출될 때 텍스트를 찍기 위해서
            <em>console.log</em>를 사용했습니다. 또 HTTP 서버를 
            <em>시작하자마자</em> 다른 텍스트를 하나 찍었습니다.
        </p>

        <p>
            이것을 실행하면(<em>node server.js</em>), “Server has started”라고 
            커맨드라인에 찍힙니다. 서버에 요청을 할 때마다(브라우저로 
            <a href="http://localhost:8888/" rel="nofollow">http://localhost:8888/</a>
           을 열어서) “Request received.” 라고 커맨드 라인에 찍힙니다.
        </p>

        <p>
            callback을 가진 이벤트 드리븐 비동기 서버사이드 JavaScript가 
            동작하다! :-)
        </p>

        <p>
            (한번의 브라우저 요청에 “Request received.” 메시지가 두번 STDOUT으로
            찍히는 것은 대부분의 브라우저가 http://localhost:8888/을 요청할 때 
            http://localhost:8888/favicon.ico를 로드하려고 하기 때문이에요).
        </p>

        <a name="how-our-server-handles-requests"></a>

        <h3>우리 서버는 요청을 어떻게 처리하는가?</h3>

        <p>
            네. 이제 나머지 코드를 얼른 분석해 봅시다. 바로 callback 함수인 
            <em>onRequest()</em>  입니다.
        </p>

        <p>
            callback으로 <em>onRequest()</em> 함수가 호출될때 두 개의 파라미터가
            넘어옵니다. <em>reqeust</em>와 <em>response</em> 죠.
        </p>

        <p>
            이것들은 객체인데요, HTTP 요청을 자세히 핸들링하거나 
            응답을 보내는데에 이 객체들의 메소드를 사용할 수 있습니다.
        </p>

        <p>
            우리 코드는 요청이 올 때마다 <em>response.writeHead()</em> 함수를 
            사용해서 HTTP status 200 과 content-type을 응답 헤더로 보내고, 
            <em>response.write()</em> 함수로 “Hello World” 텍스트를 
            HTTP 응답 바디로 보냅니다.
        </p>

        <p>
            마지막으로 <em>response.end()</em>로 응답을 마무리하죠.
        </p>

        <p>
            여기서는 요청의 자세한 내용에 대해서 신경 쓰지 않았습니다. 
            그래서 <em>request</em> 객체는 사용하지 않았죠.
        </p>

        <a name="finding-a-place-for-our-server-module"></a>

        <h3>server 모듈의 위치 잡기</h3>

        <p>
            네. 제가 나중에 애플리케이션을 구조화 하겠다고 약속했었죠?
            지금 우리는 기본적인 HTTP 서버 코드가 있는 <em>server.js</em> 파일과
            모듈들을 적재하고 애플리케이션을 시작시키는 main file인
            <em>index.js</em> 파일을 가지고 있습니다.
        </p>

        <p>
            server.js를 Node.js 모듈로 만들어서 아직 작성하지 않은 
            <em>index.js</em> main 파일에서 사용하도록 해 봅시다.
        </p>

        <p>
            아시는 것처럼, 아래와 같이 우리 코드에서 이미 모듈을 사용하고 있지요.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="pun">...</span><span
                class="pln"><br><br>http</span><span class="pun">.</span><span class="pln">createServer</span><span
                class="pun">(...);</span></pre>

        <p>
            Node.js의 내부 어딘가에 “http” 라는 모듈이 있으며, 
            이를 require 하고 지역 변수에 할당해서 사용할 수 있습니다.
        </p>

        <p>
            이렇게 하면 지역변수가 <em>http</em> 모듈이 제공하는 모든 
            public 메소드를 사용할 수 있는 객체가 됩니다.
        </p>

        <p>
            모듈의 이름으로 지역변수의 이름을 선택하는 것이 일반적이지만, 
            우리가 원하는 이름으로 지역변수 이름을 선택할 수도 있습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> foo </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="pun">...</span><span
                class="pln"><br><br>foo</span><span class="pun">.</span><span class="pln">createServer</span><span
                class="pun">(...);</span></pre>

        <p>
            좋습니다. Node.js의 내부모듈을 사용하는 것은 확실히 알겠군요. 
            그럼 모듈을 어떻게 직접 만들고 사용할 수 있을까요?
        </p>

        <p>
            <em>server.js</em> 스크립트를 모듈로 만들면서 알아봅시다.
        </p>

        <p>
            사실 별로 수정할 것도 없습니다. 코드를 모듈로 만든다는 것은 
            모듈을 필요로 하는 스크립트에 제공할 기능의 일부를 
            <em>export</em> 하는 것입니다.
        </p>

        <p>
            export 할 필요가 있는 우리 HTTP 서버의 기능은 단순합니다. 
            우리 서버모듈을 require 하는 스크립트는 
            단순히 서버를 시작하는 것이 필요한 거죠.
        </p>

        <p>
            이렇게 하기 위해, 서버 코드를 <em>start</em> 라는 함수 안에 넣고 
            이 함수를 export 하겠습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
                class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request received."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            이런 방식으로 main 파일인 <em>index.js</em>를 만들고, 
            HTTP 서버를 시작시킬 수 있습니다. 
            server에 대한 코드는 <em>server.js</em> 파일에 있지만요.
        </p>

        <p>
            <em>index.js</em> 파일을 만들고 내용을 아래와 같이 만듭시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> server </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"./server"</span><span
                class="pun">);</span><span class="pln"><br><br>server</span><span class="pun">.</span><span class="pln">start</span><span
                class="pun">();</span></pre>

        <p>
            보시다시피, 우리 서버 모듈을 다른 내장 모듈과 똑같이 사용할 수 
            있습니다: 파일을 require 하고, 지역변수에 할당하면 export 된 
            함수를 쓸 수 있게 되지요.
        </p>

        <p>
            됐습니다. 이제 main 스크립트를 통해 애플리케이션을 구동해서 기존과 
            완전히 동일하게 동작하는지 봅시다.
        </p>
        <pre>node index.js</pre>

        <p>
            대단하죠. 이제 애플리케이션의 다른 부분을 다른 파일에 넣고 그것들을
            모듈로 만들어서 서로 엮을 수 있게 되었습니다.
        </p>

        <p>
            아직 우리는 애플리케이션의 아주 초기 부분만을 만들었습니다. 
            단지 HTTP 요청을 받는거죠. 이제 요청을 가지고 뭔가를 할 필요가 있죠.
            브라우저가 요청한 URL에 따라 반응을 다르게 하는 겁니다.
        </p>

        <p>
            아주 단순한 애플리케이션이라면 이 작업을 <em>onRequest()</em> 
            callback 함수에 구현할 수 있죠. 하지만 우리 애플리케이션이 좀 더 
            재밌기 위해서 좀 더 추상화를 해보자구요.
        </p>

        <p>
            다른 HTTP 요청이 코드의 다른 부분을 가리키도록 하는 것을 
            “라우팅(routing)” 이라고 합니다. 
            자 그럼 <em>router</em>를 만들어 봅시다.
        </p>

        <a name="whats-needed-to-route-requests"></a>

        <h3>요청을 "route" 하려면?</h3>

        <p>
            요청 URL과 GET/POST 파라미터를 router로 전달하면 router는 어떤 
            코드를 실행할지 결정할 수 있어야 합니다. 
            (이 실행할 코드는 우리 애플리케이션의 세 번째 부분이에요: 
            요청을 받았을 때 실제 일을 하는 request handler 들의 집합입니다.)
        </p>

        <p>
            따라서, HTTP 요청에서 URL과 GET/POST 파라미터를 뽑아내야 합니다. 
            이것을 router 부분에서 구현해야 하는지 server 부분(혹은 server 모듈)
            부분에서 구현해야 하는지는 논란의 여지가 있습니다.
            일단 지금은 HTTP server의 일부로 만들어 봅시다.
        </p>

        <p>
            우리에게 필요한 모든 정보는 <em>request</em> 객체를 - callback 함수인
            <em>onRequest()</em> 함수의 첫 번째 파라미터로 전달받은 - 통해 
            접근할 수 있습니다. 하지만 이 정보를 얻어내기 위해 <em>url</em> 과 
            <em>querystring</em> 이라는 모듈이 추가로 필요합니다. 
        </p>

        <p>
            <em>url</em> 모듈은 URL의 각각의 부분 
            (예를들면 URL path와 query string)
           을 뽑아낼 수 있는 메소드를 제공합니다.
            <em>querystring</em>은 query string을 request 파라미터로 파싱 
            하는데 사용합니다.
        </p>
<pre>                               url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&amp;hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]
</pre>

        <p>
            나중에 보겠지만 <em>querystring</em> 모듈을 POST 요청의 body를 
            파싱하는데에도 사용할 수 있습니다.
        </p>

        <p>
            브라우저가 요청한 URL path가 무엇인지 알 수 있도록 하는 로직을 
            <em>onRequest()</em> 함수에 추가해 봅시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
                class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            좋아요. 이제 URL path를 기준으로 요청을 구분할 수 있게 되었습니다. 
            이걸 이용하면 URL path를 기반으로 요청을 request handler로 매핑하는 
            router(아직 안 만들었죠)를 만들 수 있겠네요.
        </p>

        <p>
            우리 애플리케이션 관점에서 보면, <em>/start</em> 요청과 
            <em>/upload</em> 요청을 각각 다른 코드에서 처리하도록 
            할 수 있다는 것입니다. 
            곧 모든 것이 어떻게 맞아떨어지는지 보게 될겁니다.
        </p>

        <p>
            좋아요. 이제 진짜로 router를 만듭시다. <em>router.js</em> 라는 새 
            파일을 만들고 내용을 아래와 같이 입력합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">pathname</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            네. 이 코드는 기본적으로 아무것도 안 하죠. 
            하지만 지금은 이걸로 좋습니다.  router에 좀 더 로직을 추가하기 전에
            일단 이 router를 server와 어떻게 엮을지 봅시다.
        </p>

        <p>
            HTTP server가 router를 사용한다는 것을 알게 해야 합니다. 
            이 의존성을 강하게 만들 수도 있지만 다른 프로그래밍 언어를 통해 
            배운 대로 dependency injection을 통해 server와 router를 느슨하게 
            결합할 겁니다.(배경지식을 위해 Martin Fowler 의
            <a href="http://martinfowler.com/articles/injection.html"> Dependency Injection에 대한 좋은 포스트</a>를 
            읽어보는걸 추천합니다.)
        </p>

        <p>
            먼저 router 함수를 파라미터로 넘길 수 있도록 server의 
            <em>start()</em> 함수를 확장합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
                class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; route</span><span class="pun">(</span><span
                class="pln">pathname</span><span class="pun">);</span><span
                class="pln"><br><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            그리고 <em>index.js</em>를 확장합니다. 
            여기서 router 함수를 server로 주사(inject) 합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> server </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"./server"</span><span
                class="pun">);</span><span class="pln"><br></span><span class="kwd">var</span><span
                class="pln"> router </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"./router"</span><span class="pun">);</span><span class="pln"><br><br>server</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">(</span><span
                class="pln">router</span><span class="pun">.</span><span class="pln">route</span><span
                class="pun">);</span><span class="pln"><br></span></pre>

        <p>
			여기서도 다시 함수를 넘기고 있지요. 
			이런 것은 이제 우리에게 새로울 것도 없습니다.
        </p>

        <p>
            이제 애플리케이션을 시작하고(<em>node index.js</em>), 
            URL을 요청하면, 애플리케이션의 출력으로 HTTP server가 router를 
            사용하고 pathname을 넘기는 것을 볼 수 있습니다.
        </p>
        <pre>bash$ node index.js
Request for /foo received.
About to route a request for /foo</pre>

        <p>
            (다소 짜증나는 /favicon.ico 요청 관련 출력은 생략했어요).
        </p>

        <a name="execution-in-the-kongdom-of-verbs"></a>

        <h3>동사들(verbs)의 나라에서의 실행(execution)</h3>

        <p>
            잠깐 functional programming 에 대해 이야기를 해볼게요.
        </p>

        <p>
            함수를 전달하는 것은 단지 기술적인 고려사항이 아니에요. 
            소프트웨어 디자인의 관점에서 보면 이것은 거의 철학적인 이야기입니다. 
            잠깐 생각해 봅시다. index 파일에서 <em>router</em> 객체를 server로 
            전달할 수도 있고, server 는 이 객체의 <em>route</em> 함수를 
            호출할 수도 있습니다.
        </p>

        <p>
            이 방식으로 우리는 물건(thing)을 전달하고 server는 무슨 일인가를 
            하는데에 이 물건(thing)을 사용합니다. 
            헤이 router야~~, 이것 좀 보내(route) 줄래?
        </p>

        <p>
            하지만 server는 그런 것(thing)이 필요 없죠. 다만 뭔가를 <em>할</em> 
            필요가 있는 것 뿐 입니다. 그리고 뭔가를 하려면 물건(things)이 
            필요한 게 아니라 <em>행동(actions)</em>이 필요하죠. 
            <em>명사(nouns)</em>는 필요 없고 <em>동사(verbs)</em>가 필요합니다.
        </p>

        <p>
            이 아이디어의 핵심에 있는 근본적인 정신변화를 이해하니 
            functional programming을 진정으로 이해할 수 있었습니다.
        </p>

        <p>
            Steve Yegge의 걸작 
            <a href="http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html">Execution in the Kingdom of Nouns</a> 
           을 읽었을 때 이것을 이해했습니다. 지금 읽어보세요. 
            이것은 제가 본 소프트웨어와 관련된 최고의 저술 중에 하나입니다.
        </p>

        <a name="routing-to-real-request-handlers"></a>

        <h3>실제 request handler로 라우팅(routing) 하기</h3>

        <p>
            비즈니스로 돌아옵시다. 이제 우리가 의도한 대로 HTTP server와 
            router는 친구가 되어서 서로 이야기를 나눕니다.
        </p>

        <p>
            당연히, 이걸로는 부족합니다. 
            “Routing” 은 다른 URL을 다르게 처리하고 싶다는 말이죠. 
            <em>/start</em> 요청에 대한 “비즈니스 로직”은 
            <em>/upload</em> 요청과는 다른 함수에서 처리하고 싶습니다.
        </p>

        <p>
            router는 요청에 대해 실제로 뭔가를 할 만한 곳이 아닙니다. 
            애플리케이션이 더 복잡해지면 router를 확장하기가 쉽지가 않아집니다.
        </p>

		<p>
            요청이 route 될 함수를 request handler 라고 부르기로 하고 
            곧바로 뛰어들어가 봅시다.
        </p>

		<p>
            새로운 애플리케이션 부분이니까 새 모듈로 만들어야겠습니다. 
            requestHandlers 라는 모듈을 만들고, 각각의 request handler를 위한 
            껍데기(placeholder) 함수들을 추가한 후 
            이 모듈의 메소드로 export 합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span
                class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            이제 router와 request handler를 엮었으므로 우리 router가 
            어딘가로 route 할 수 있게 되었습니다.
        </p>

        <p>
            이 시점에 결정이 필요합니다: requestHandler 모듈을 router에 
            하드코딩 된 방식으로 묶을 것이냐, 아니면 의존관계 주입(dependency injection)으로 좀 더 처리할 것이냐?
            모든 패턴과 마찬가지로 의존 관계 주입은 그 자체를 위해 
            사용하는 것이 아닙니다. 
            여기에서는 router와 request handler를 느슨하게 묶어서 
            router의 재사용을 크게 높입니다.
        </p>

        <p>
            이렇게 하려면 request handler를 server에서 router로 전달해야 하는데,
            이건 더 잘못된 느낌을 줍니다. 왜냐하면 main 파일에서 server로 보내고
            server에서 router로 보내야 하기 때문이죠.
        </p>

        <p>
            그럼 어떻게 전달하는 게 좋을까요? 지금은 두 개의 handler가 있지만 
            실제 애플리케이션에서는 handler의 수가 늘어나고 다양해 질 겁니다. 
            그리고 새 URL request handler가 추가될 때마다 router에서 
            request와 handler를 매핑하는 일을 하고 싶진 않습니다. 
            게다가 <em>if request == x then call handler y</em>와 같은 코드는 
            추악함 이상이 될겁니다.
        </p>

        <p>
            다양한 항목이 있고, 각각은 (요청된 URL)문자열에 매핑된다?
            오, 연관배열이 딱 맞아떨어질것 같긴 합니다만..
        </p>

        <p>
            음. 조금 실망스럽게도 JavaScript는 연관배열을 지원하지 않는답니다.
            그런데, 알고보니 연관배열이 필요한 경우에는 객체를 사용하면 
            된다는군요.
        </p>

        <p>
            여기 좋은 소개가 있습니다.
            <a href="http://msdn.microsoft.com/en-us/magazine/cc163419.aspx">http://msdn.microsoft.com/en-us/magazine/cc163419.aspx</a>,
            관련된 부분을 인용해 보면:
        </p>
        <blockquote>
            <p>
                C++과 C#에서, 객체는 class나 struct의 인스턴스를 지칭합니다. 
                객체는 그것이 어떤 템플릿(이를테면, class)으로 인스턴스화 되었느냐에 따라
                다른 프로퍼티와 메소드를 가집니다. (하지만) JavaScript 객체는 다릅니다. 
                JavaScript에서 객체는 단지 이름/값 쌍의 컬렉션에 불과합니다. 
                - JavaScript 객체는 키 값이 문자열인 사전(dictionary)이라고 생각하세요.
            </p>
        </blockquote>

        <p>
            만약 JavaScript 객체가 단순히 이름/값 쌍의 컬렉션이라면 어떻게 
            메소드를 가질 수 있죠? 네, 값은 문자열 일수도 숫자일수도 
            함수!일 수도 있습니다.
        </p>

        <p>
            오케이, 다시 코드로 돌아와서 requestHandlers의 리스트를 객체로 
            넘기고, 느슨한 연결을 위해 이 객체를 
            <em>route()</em>로 주사(inject) 하려고 합니다.
        </p>

        <p>
            이 객체를 main 파일인 <em>index.js</em>에 넣어 봅시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> server </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"./server"</span><span
                class="pun">);</span><span class="pln"><br></span><span class="kwd">var</span><span
                class="pln"> router </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"./router"</span><span class="pun">);</span><span class="pln"><br></span><span class="kwd">var</span><span
                class="pln"> requestHandlers </span><span class="pun">=</span><span class="pln"> require</span><span
                class="pun">(</span><span class="str">"./requestHandlers"</span><span class="pun">);</span><span
                class="pln"><br><br></span><span class="kwd">var</span><span class="pln"> handle </span><span
                class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span
                class="pln"><br>handle</span><span class="pun">[</span><span class="str">"/"</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">;</span><span class="pln"><br>handle</span><span
                class="pun">[</span><span class="str">"/start"</span><span class="pun">]</span><span
                class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">;</span><span class="pln"><br>handle</span><span
                class="pun">[</span><span class="str">"/upload"</span><span class="pun">]</span><span
                class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">upload</span><span class="pun">;</span><span class="pln"><br><br>server</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">(</span><span
                class="pln">router</span><span class="pun">.</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">);</span></pre>

        <p>
            <em>handle</em>은 "사물(thing)" (여기에선 request handler들의 컬렉션)에 
            가깝지만 동사처럼 이름을 지었습니다. 
            곧 보게 되겠지만 결과적으로 router의 멋진 표현(방식)이 될 겁니다.
        </p>

        <p>
            보시는 바와 같이, 다른 URL을 동일한 request handler에 매핑하는 것은 매우 
            쉽습니다. 키/값 쌍에 <em>"/"</em>와 <em>requestHandlers.start</em>
           를 추가하면 <em>/start</em> 요청뿐 아니라 <em>/</em> 요청도 
            <em>start</em> handler로 연결됩니다.
        </p>

        <p>
            객체를 정의한 후에 server에게 별도의 파라미터로 전달합니다. 
            <em>server.js</em>를 다음과 같이 바꿉시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; route</span><span class="pun">(</span><span
                class="pln">handle</span><span class="pun">,</span><span class="pln"> pathname</span><span class="pun">);</span><span
                class="pln"><br><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            <em>start()</em> 함수에 <em>handle</em> 파라미터를 추가했고 handle 
            객체를 <em>route()</em> callback 에 첫 번째 파라미터로 넘겼습니다.
        </p>

        <p>
            이제 <em>route()</em> 함수를 수정해야죠. 
            <em>router.js</em> 파일입니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">handle</span><span class="pun">,</span><span
                class="pln"> pathname</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">if</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span
                class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span
                class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; handle</span><span
                class="pun">[</span><span class="pln">pathname</span><span class="pun">]();</span><span class="pln"><br>&nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"No request handler found for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            여기에 우리가 해야 할 일은, 주어진 pathname에 해당하는 request handler가 있는지
            체크하고, 존재하면 그 함수를 호출하는 겁니다. 
            연관배열에서 요소에 접근하는 것처럼 객체에서 request handler 함수에
            접근할 수 있으므로, “<em>pathname</em>을 <em>handle</em> 해줘~”로 읽히는 멋진 <em>handle[pathname]();</em> 함수를 갖게 되었습니다. 
        </p>

        <p>
            좋군요. 이것이 server와 router 그리고 request handler를 함께 묶기 위해 필요한 
            전부입니다. 애플리케이션을 실행하고 브라우저로 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a>
           를 요청하면 정확한 request handler가 호출된 것을 확인할 수 있습니다.
        </p>
        <pre>Server has started.
Request for /start received.
About to route a request for /start
Request handler 'start' was called.</pre>

        <p>
            브라우저로 
            <a href="http://localhost:8888/" rel="nofollow">http://localhost:8888/</a> 
           을 열면 역시 <em>start</em> request handler가 동작합니다.
        </p>
        <pre>Request for / received.
About to route a request for /
Request handler 'start' was called.</pre>

        <a name="making-the-request-handlers-respond"></a>

        <h3>request handler가 응답하게 만들기</h3>

        <p>
            아름답지요? 이제 오직 request handler만이 브라우저에게 뭔가를 
            보낼 수 있게 된다면 한결 좋아지겠죠. 그렇죠?
        </p>

        <p>
            기억해 봅시다. 브라우저에 찍히는 “Hello World” 는 여전히 
            <em>server.js</em> 파일의 <em>onRequest</em> 함수에서 오는거죠.
        </p>

        <p>
            결국 “request 처리”란 “request에 응답하는 것”입니다. 
            이제 <em>onRequest</em>가 하는 것처럼 request handler가 
            브라우저에 이야기할 수 있게 해줘야 합니다.
        </p>

        <a name="how-to-not-do-it"></a>

        <h4>해서는 안되는 것</h4>

        <p>
            PHP나 Ruby 배경을 가진 개발자처럼 직관적인 접근 방식을 따르고 싶을 
            수 있는데, 매력적이고 상당히 그럴듯해 보이지만, 
            예상치 못한 때에 갑자기 망쳐버릴 수 있습니다.
        </p>

        <p>
            “직관적인 접근 방식”이란 이런 겁니다. 
            requesthandler는 사용자에게 보여주려는 내용을  
            <em>return()</em>하고, 그러면
            <em>onRequest</em> 함수는 이 응답 데이터를 user에게 보내는 방식입니다.
        </p>

        <p>
            이렇게 한번 해보고, 이게 왜 그리 좋지 않은 아이디어인지 봅시다.
        </p>

        <p>
            우리는 request handler로부터 시작해서, 브라우저에 표시하고자 하는 내용을 request handler가 return하도록 만듭니다. 
            <em>requestHandlers.js</em>를 다음과 같이 고칠 필요가 있습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">return</span><span
                class="pln"> </span><span class="str">"Hello Start"</span><span class="pun">;</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> upload</span><span class="pun">()</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span
                class="str">"Request handler 'upload' was called."</span><span class="pun">);</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">return</span><span class="pln"> </span><span
                class="str">"Hello Upload"</span><span class="pun">;</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            좋군요. 마찬가지로 router는 request handler가 return 한 것을 
            server에게 return 해야 합니다. 따라서, <em>router.js</em>를 다음과 같이 고칩니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">handle</span><span class="pun">,</span><span
                class="pln"> pathname</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">if</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span
                class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span
                class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">return</span><span class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"No request handler found for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">return</span><span
                class="pln"> </span><span class="str">"404 Not found"</span><span class="pun">;</span><span class="pln"><br>&nbsp; </span><span
                class="pun">}</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            보시다시피, route 못하는 요청이 있으면 
            약간의 텍스트를 return 하게 했습니다.
        </p>

        <p>
            마지막으로, <em>server.js</em>를 아래와 같이 바꿔서 
            request handler가 router를 통해 return 한 내용을 
            브라우저에 응답하도록 수정합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">var</span><span class="pln"> content </span><span
                class="pun">=</span><span class="pln"> route</span><span class="pun">(</span><span
                class="pln">handle</span><span class="pun">,</span><span class="pln"> pathname</span><span
                class="pun">)</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">content</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            수정한 애플리케이션을 다시 구동하면 모든 것이 매력적으로 동작합니다. 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a>를 요청하면 “Hello Start”가 출력되고, 
            <a href="http://localhost:8888/upload" rel="nofollow">http://localhost:8888/upload</a>는 “Hello Upload”가, 
            <a href="http://localhost:8888/foo" rel="nofollow">http://localhost:8888/foo</a>는 “404 Not found”가 나옵니다.
        </p>

        <p>
            좋아요. 그런데 이게 왜 문제라는 거죠? 짧게 대답하자면 이렇습니다. 나중에 request handler 중 
            하나가 non-blocking 동작을 해야할 때 문제에 생기기 때문입니다.
        </p>

        <p>
            좀 더 긴 대답을 들어 봅시다.
        </p>

        <a name="blocking-and-non-blocking"></a>

        <h4>Blocking 과 non-blocking</h4>

        <p>
            이야기 했듯이, 문제는 request handler에 non-blocking 동작을 
            포함시킬 때 발생합니다. 먼저 blocking 동작에 대해 이야기를 하고, 
            그 후에 non-blocking 동작에 대해 이야기 할게요.
        </p>

        <p>
            그리고 “blocking” 과 “non-blocking”의 뜻을 설명하는 대신에 
            request handler에 blocking 동작을 추가할 때 무슨 일이 생기는지 
            직접 보여 드리겠습니다.
        </p>

        <p>
            이를 위해, <em>start</em> request handler에서 “Hello Start” 문자열을
            return 하기 전에  10초 동안 기다리도록 수정할 겁니다. 
            JavaScript에 <em>sleep()</em> 같은 건 없기 때문에 
            다른 짓을 해야 합니다.
        </p>

        <p>
            <em>requestHandlers.js</em>를 아래와 같이 고칩시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> sleep</span><span class="pun">(</span><span class="pln">milliSeconds</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> startTime </span><span class="pun">=</span><span
                class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span
                class="typ">Date</span><span class="pun">().</span><span class="pln">getTime</span><span
                class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">while</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span
                class="pln"> </span><span class="typ">Date</span><span class="pun">().</span><span
                class="pln">getTime</span><span class="pun">()</span><span class="pln"> </span><span
                class="pun">&lt;</span><span class="pln"> startTime </span><span class="pun">+</span><span class="pln"> milliSeconds</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; sleep</span><span class="pun">(</span><span class="lit">10000</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">return</span><span
                class="pln"> </span><span class="str">"Hello Start"</span><span class="pun">;</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> upload</span><span class="pun">()</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span
                class="str">"Request handler 'upload' was called."</span><span class="pun">);</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">return</span><span class="pln"> </span><span
                class="str">"Hello Upload"</span><span class="pun">;</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            이게 무엇을 하는 것인지 살펴보면: <em>start()</em> 함수가 호출되면 
            Node.js는 10초를 기다리고 “Hello Start”를 return 합니다. 
            <em>upload()</em>를 호출하면 기존처럼 곧바로 return 합니다.
        </p>

        <p>
            (10초를 sleep 하는 것 말고 다른 것을 상상할 수도 있겠죠. 오랜 시간이 
            걸리는 계산과 같은 blocking operation 이 start() 안에 존재할 수 있습니다.)
        </p>

        <p>
            이 변화가 무엇을 의미하는지 봅시다.
        </p>

        <p>
            애플리케이션을 재시작 한 후에 무슨 일이 일어나는지 보기 위해 조금 
            복잡한 절차를 따라주세요. 첫째, 브라우저 두 개나 탭 두 개를 열어주세요. 
            첫 번째 브라우저의 주소창에 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a>를 
            입력만 하고 아직은 이 URL로 이동하진 마세요.
        </p>

        <p>
            두 번째 브라우저의 주소창에 
            <a href="http://localhost:8888/upload" rel="nofollow">http://localhost:8888/upload</a>를 
            입력하고 역시 엔터를 치지는 말아주세요.
        </p>

        <p>
            이제 다음과 같이 합니다.: 첫 번째 윈도우(“/start”)에 엔터를 치고 
            재빨리 두 번째 윈도우(“/upload”)로 가서 엔터를 칩니다.
        </p>

        <p>
            우리가 예상한 대로 /start URL은 로드하는데 10초가 걸립니다. 
            하지만 /upload 의 request handler에는 <em>sleep()</em>이 없음에도
            불구하고 /upload URL <em>또한</em> 로드하는 데 10초가 걸립니다. 
        </p>

        <p>
            왜요? <em>start()</em>가 blocking 동작을 포함하기 때문이죠. 
            마치 “다른 모든 것을 일하지 못하게 막는 것”과 같죠.
        </p>

        <p>
            <em>“node에서는 모든 게 병렬로 수행된다. 당신 code만 빼고.”</em>라는
            말처럼 이건 문제입니다.
        </p>

        <p>
            Node.js는 다수의 동시작업을 처리할 수 있지만 thread를 나누는 
            방식으로 하지 않습니다. 사실 Node.js는 단일 thread입니다. 
            대신, Node.js는 동시작업을 event loop을 실행해서 처리하며 개발자들은 
            이것을 사용할 수 있습니다. 
            우리는 blocking 동작을 피하고 non-blocking 동작을 사용해야만 합니다.
        </p>

        <p>
            그러기 위해서는 callback으로 함수를 다른 함수에게 넘겨야 합니다.
            언젠가 어떤 이벤트가 발생하면 (예를들면 10초 sleep을 한다거나,
            database에 질의를 하거나, 값비싼 계산을 하거나) 
            이 함수를 호출하게 되겠지요.
        </p>

        <p>
            이런식으로 이야기 하는거죠. <em>“헤이, probablyExpensiveFunction(),
            니 일을 해줘. 하지만 나 Single Node.js 쓰레드는 네가 끝낼 때까지 
            여기서 기다리지 않을거야. 네 아래에 있는 코드 라인을 계속 실행할거야.
            그러니 여기 이 callbackFunction()을 가져가서 네가 너의 비싼 일을 
            모두 끝냈을 때 호출해 주겠니? 고마워!”</em>
        </p>

        <p>
            (이것에 대해 더 자세히 읽고 싶다면 Mixu의 
            <a href="http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/">Understanding the node.js event loop</a>. 
            라는 포스트를 살펴보세요)
        </p>

        <p>
            이제 우리가 만들었던 “request handler가 response를 handling” 하는 
            식의 방법이 왜 non-blocking 동작을 제대로 하지 못하도록 하는지 
            살펴봅시다.
        </p>

        <p>
            다시 한번, 먼저 애플리케이션을 수정해서 문제가 발생하는 것을 
            경험해 봅시다.
        </p>

        <p>
            이번에도 <em>start</em> request handler를 사용합니다. 
            아래와 같이 수정해 주세요(<em>requestHandlers.js</em> 파일이에요).
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> exec </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"child_process"</span><span
                class="pun">).</span><span class="pln">exec</span><span class="pun">;</span><span
                class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">var</span><span class="pln"> content </span><span
                class="pun">=</span><span class="pln"> </span><span class="str">"empty"</span><span class="pun">;</span><span
                class="pln"><br><br>&nbsp; exec</span><span class="pun">(</span><span class="str">"ls -lah"</span><span
                class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span
                class="pln"> </span><span class="pun">(</span><span class="pln">error</span><span
                class="pun">,</span><span class="pln"> stdout</span><span class="pun">,</span><span
                class="pln"> stderr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; &nbsp; content </span><span class="pun">=</span><span
                class="pln"> stdout</span><span class="pun">;</span><span class="pln"><br>&nbsp; </span><span
                class="pun">});</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">return</span><span
                class="pln"> content</span><span class="pun">;</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">return</span><span
                class="pln"> </span><span class="str">"Hello Upload"</span><span class="pun">;</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            보시는 것처럼, 우리는 새로운 Node.js 모듈인 <em>child_process</em>를
            사용했습니다. 매우 단순하지만 쓸모가 많은 non-blocking 동작인 
            <em>exec()</em>을 사용하기 위해서 입니다.
        </p>

        <p>
            <em>exec()</em>은 shell 커맨드를 Node.js 안에서 실행시킵니다. 
            이 예에서는 현재 디렉토리에 있는 모든 파일 리스트를 가져오는데 
            사용해서 브라우저가 <em>/start</em> URL을 요청할 때 이 리스트를 
            출력할 수 있습니다.
        </p>

        <p>
            코드가 매우 직관적이죠. <em>content</em> 라는 새 변수를 
            생성하고(초기값은 “empty”로), “ls -alh”를 실행하고, 
            이 결과로 변수를 채우고 변수를 return 합니다.
        </p>

        <p>
            언제나처럼 애플리케이션을 구동시키고 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a>를 방문합니다.
        </p>

        <p>
            멋진 웹페이지가 로드되고 “empty” 문자열이 출력됩니다. 
            뭐가 잘못된 거죠?
        </p>

        <p>
            짐작하셨겠지만, <em>exec()</em>이 non-blocking 방식으로 마법을 
            부렸습니다. blocking <em>sleep</em> operation 처럼 애플리케이션을 
            정지시키지 않고 상당히 비싼 shell operation
            (매우 큰 파일을 복사한다거나 하는)을  실행할 수 있게 해주기 때문에 
            exec()은 매우 좋은 겁니다.
        </p>

        <p>
            (이것을 증명하고 싶다면 “ls -lah”를 “find /” 처럼 
            더 비싼 operation 으로 바꿔 보세요)
        </p>

        <p>
            하지만 브라우저에 그 결과를 출력하지 못하기 때문에 이 우아한 
            non-blocking operation을 좋아할 수만은 없습니다. 그렇죠?
        </p>

        <p>
            그러면, 고쳐 봅시다. 그러면서 왜 지금의 아키텍쳐는 제대로 동작하지 
            않는지 이해해 보자구요.
        </p>

        <p>
            문제는 <em>exec()</em>이 non-blocking 으로 동작하기 위해서 
            callback 함수를 사용해야 한다는 것입니다.
        </p>

        <p>
            우리 예에서는 <em>exec()</em> 함수의 두 번째 파라미터로 전달한 
            anonymous 함수입니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> </span><span
                class="pun">(</span><span class="pln">error</span><span class="pun">,</span><span
                class="pln"> stdout</span><span class="pun">,</span><span class="pln"> stderr</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; content </span><span
                class="pun">=</span><span class="pln"> stdout</span><span class="pun">;</span><span
                class="pln"><br></span><span class="pun">}</span></pre>

        <p>
            그리고 여기에 문제의 뿌리가 놓여있습니다: 우리의 코드는 
            동기적으로 동작합니다. 즉 <em>exec()</em>을 호출하자 마자 Node.js는
            이어서 <em>return content;</em>를 실행합니다. 
            바로 이 시점에 <em>content</em>는 여전히 “empty” 입니다.
            왜냐하면 <em>exec()</em>은 비동기적으로 동작하기 때문에 
            <em>exec()</em>에 전달된 callback 함수는 아직 호출되지 않았던 것이죠.
        </p>

        <p>
            “ls -lah” 는 매우 싸고 빠른 operation 입니다.
            (디렉토리에 수백만 개의 파일이 존재하지 않는다면) 
            따라서 callback이 상대적으로 빠르게 호출됩니다. 
            그럼에도 불구하고 이 일은 비동기적으로 일어납니다.
        </p>

        <p>
            이것을 더욱 확실하게 보여주는 더 비싼 커맨드를 생각해 봅시다: 
            “find /” 는 제 장비에서 대략 1분이 걸리지만 request handler에서 
            “ls -lah”를 “find /”로 바꾸어도 /start URL을 요청할 때 여전히 
            즉시 HTTP 응답을 받게 됩니다. 
            이제 Node.js가 애플리케이션을 계속 실행하는 중에 <em>exec()</em>은 
            백그라운드에서 수행한다는 것이 확실합니다. 
            그리고 <em>exec()</em>에 넘긴 callback 함수는 
            “find /” 커맨드의 동작이 끝났을 때 호출될 것입니다.
        </p>

        <p>
            그럼 우리는 어떻게 현재 디렉토리의 파일 리스트를 사용자에게 
            보여주려는 우리 목표를 이룰 수 있을까요?
        </p>

        <p>
            어떻게 하면 <em>안</em> 되는지를 배웠으니까, 이제 request handler가
            브라우저에게 올바른 방식으로 응답하는 방법을 논의해 봅시다.
        </p>

        <a name="responding-request-handlers-with-non-blocking-operations"></a>

        <h4>request handler가 non-blocking 방식으로 동작하면서 응답하기</h4>

        <p>
            제가 방금 “올바른 방식” 이라는 표현을 사용했는데. 위험한 말입니다. 
            대부분은 “올바른 방식”이 하나만 존재하는 것이 아닙니다.
        </p>

        <p>
            이번 경우에는 함수를 전달하는 것이 한 방법입니다. 한번 살펴봅시다.
        </p>

        <p>
            현재 우리 애플리케이션은 사용자에게 보여주고 싶은 content를 request handler에서 HTTP server로 전달할 수 있습니다. 다음과 같은 여러 애플리케이션 레이어들을 거쳐 넘기는 식으로 식으로 말입니다.
            (request handler -&gt; router -&gt; server).
        </p>

        <p>
            새로운 접근 방법은 다음과 같습니다: content를 server로 보내는 대신 
            server를 content로 보낼겁니다. 좀 더 자세히 이야기 하면, 
            <em>response</em> 객체 (server의 callback 함수인 <em>onRequest()</em>
           에서 얻은)를 router를 통해 request handler에게 주사(inject) 합니다.
            이제 handler는 이 객체가 가진 함수들을 이용해서 스스로 요청에 응답할 수 있게 
            되었습니다.
        </p>

        <p>
            설명은 충분합니다. 이제 하나씩 애플리케이션을 고쳐 봅시다.
        </p>

        <p>
            <em>server.js</em>부터 시작합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; route</span><span class="pun">(</span><span
                class="pln">handle</span><span class="pun">,</span><span class="pln"> pathname</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">);</span><span class="pln"><br>&nbsp; </span><span
                class="pun">}</span><span class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            <em>route()</em> 함수가 값을 return 하길 기다리는 대신 세 번째 파라미터로 
            <em>response</em> 객체를 전달했습니다. 또 <em>onRequest()</em>에서는
            <em>response</em>의 메소드 호출을 모두 제거했습니다. 
            이제 <em>route</em>가 처리해야 하니까요.
        </p>

        <p>
            다음은 router.js 입니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">handle</span><span class="pun">,</span><span
                class="pln"> pathname</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">if</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span
                class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span
                class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; handle</span><span
                class="pun">[</span><span class="pln">pathname</span><span class="pun">](</span><span class="pln">response</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"No request handler found for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">404</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"404 Not found"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            비슷한 패턴입니다: request handler가 return 하도록 하는 대신 
            <em>response</em> 객체를 전달했습니다.
        </p>

        <p>
            마땅한 request handler를 찾지 못하는 경우 직접 “404” header와 
            body를 응답하도록 처리해야 합니다.
        </p>

        <p>
            이제 마지막으로 <em>requestHandlers.js</em> 입니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> exec </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"child_process"</span><span
                class="pun">).</span><span class="pln">exec</span><span class="pun">;</span><span
                class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; exec</span><span class="pun">(</span><span
                class="str">"ls -lah"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span
                class="pln"> </span><span class="pun">(</span><span class="pln">error</span><span
                class="pun">,</span><span class="pln"> stdout</span><span class="pun">,</span><span
                class="pln"> stderr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">stdout</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">});</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> upload</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello Upload"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            handler 함수가 response를 파라미터로 받았고 request에 응답하기 위해
            이 객체를 직접 사용하고 있습니다.
        </p>

        <p>
            <em>start</em> handler는 <em>exec()</em> 함수의 anonymous callback
           에서 응답합니다. 그리고 <em>upload</em> handler는 여전히 단순하게 
            “Hello Upload”를 응답하지만 이번에는 직접 <em>response</em> 객체를
            사용하지요.
        </p>

        <p>
            이제 애플리케이션을 다시 시작하면(<em>node index.js</em>) 
            제대로 동작할 겁니다.
        </p>

        <p>
            <em>/start</em> 요청에 있는 비싼 동작에도 불구하고  
            <em>/upload</em> 요청이 곧바로 응답되는 것을 (block 되지 않고) 
            확인하고 싶다면, 아래와 같이 <em>requestHandlers.js</em>를 
            고쳐보세요.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> exec </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"child_process"</span><span
                class="pun">).</span><span class="pln">exec</span><span class="pun">;</span><span
                class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; exec</span><span class="pun">(</span><span
                class="str">"find /"</span><span class="pun">,</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">{</span><span class="pln"> timeout</span><span class="pun">:</span><span
                class="pln"> </span><span class="lit">10000</span><span class="pun">,</span><span
                class="pln"> maxBuffer</span><span class="pun">:</span><span class="pln"> </span><span
                class="lit">20000</span><span class="pun">*</span><span class="lit">1024</span><span
                class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span
                class="pln">error</span><span class="pun">,</span><span class="pln"> stdout</span><span
                class="pun">,</span><span class="pln"> stderr</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span
                class="pln">stdout</span><span class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">});</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span
                class="kwd">function</span><span class="pln"> upload</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello Upload"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            이렇게 하면 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a> 
            에 대한 요청이 최소한 10초가 걸리게 되지만 
            /start가 여전히 동작 중일 때에도 
            <a href="http://localhost:8888/upload" rel="nofollow">http://localhost:8888/upload</a> 
            요청은 곧바로 응답합니다.
        </p>

        <a name="serving-something-useful"></a>

        <h3>유용한 것을 제공하기</h3>

        <p>
            지금까지 우리가 한 일은 멋지긴 했습니다만, 
            우리의 멋진 사이트로 고객에게 가치를 제공하지는 못했습니다.
        </p>

        <p>
            server, router, request handlers가 있으니 이제  사이트에 컨텐트를 
            추가해서 사용자가 파일을 선택하고, 이 파일을 업로드하고, 
            업로드한 파일을 보는 유스케이스를 제공할 수 있습니다. 
            단순하게 하기 위해 이미지 파일만 업로드 하고 볼 수 있다고 
            가정하겠습니다.
        </p>

        <p>
            네. 이제 하나씩 해 봅시다. 대부분 지금까지 다룬 JavaScript 테크닉과 
            이론을 가지고 할 겁니다. 그리고 조금 새로운 것도 나올 겁니다.
        </p>

        <p>
            하나씩이라고 했는데 두 단계입니다: 
            첫 번째로 POST 요청(파일 업로드는 아니지만)을 처리하는 방법을 
            살펴볼 겁니다. 
            두 번째는 파일 업로드를 처리하기 위해 Node.js의 외부 모듈을 사용할 
            겁니다. 제가 이런 방식을 선택한 이유는 두 가지가 입니다.
        </p>

        <p>
            첫째, Node.js로 기본적인 POST 요청을 처리하는 것은 상대적으로 
            쉽습니다만 연습해 볼 가치는 충분합니다.
            <br>
            둘째, Node.js로 파일 업로드( 즉 multipart POST 요청)를 처리하는 것은
            <em>간단하지 않아서</em> 이 튜토리얼의 범위를 넘어갑니다. 
            하지만 외부 모듈을 사용하는 것은 그 자체로 의미가 있어서 
            beginner 튜토리얼에 포함할만 합니다.
        </p>

        <a name="handling-post-requests"></a>

        <h4>POST 요청 처리하기</h4>

        <p>
            뻔하고 단순한 것으로 합시다: textarea를 하나 제공해서 사용자가 
            내용을 채우고 submit 해서 POST 요청을 서버로 보냅니다. 
            이 요청을 받아서 textarea 내부의 내용을 출력하겠습니다.
        </p>
        
        <p>
            <em>/start</em> 요청에서 textarea를 위한 HTML을 뿌려줘야 하니까 
            <em>requestHandler.js</em>에 추가해 봅시다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" content="text/html; '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'charset=UTF-8" /&gt;'</span><span class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" method="post"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;textarea name="text" rows="20" cols="60"&gt;&lt;/textarea&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Submit text" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/html&gt;'</span><span class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"Hello Upload"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            이제 이 사이트가 Webby Awards(국제 우수 웹사이트 상)을 받지 않는다면
            누가 받을까 모르겠네요. 브라우저로 
            <a href="http://localhost:8888/start" rel="nofollow">http://localhost:8888/start</a> 
           를 요청하면 이 단순한 form을 볼 수 있습니다. 
            만약 안된다면 애플리케이션을 재시작 안 했을 겁니다.
        </p>

        <p>
            view 컨텐트를 request handler 안에 가지고 있는 게 추악하다구요? 
            하지만 저는 이 튜토리얼에 더 이상의 추상화 
            (즉, view와 controller 로직을 분리하는 것)를 하지 않기로 했습니다. 
            그렇게 하는 것이 JavaScript나 Node.js를 설명하는 관점에서는
            의미 있는 것이 아니라고 생각하기 때문입니다.
        </p>

        <p>
            그보다 좀 재미있는 문제를 봅시다. 사용자가 이 form을 submit 할 때 
            POST 요청은 <em>/upload</em> request handler로 갑니다.
        </p>

        <p>
            이제 우린 전문가 같은 초보가 되고 있으니까, POST 데이터가 비동기 
            callback을 사용해서 non-blocking 방식으로 처리된다는 것이 
            놀랍지 않습니다.
        </p>

        <p>
            POST 요청은 상당히 클겁니다. 누구도 사용자가 몇 메가바이트의 
            텍스트를 입력하는 것을 막을 수 없겠죠. 전체 데이터 블록을 하나로 
            처리하는 것은 blocking operation 방법이 될 것입니다.
        </p>

        <p>
            전체 프로세스를 non-blocking 으로 만들려면, 
            POST 데이터를 작은 청크로 나누고 특정 이벤트 때마다 
            callback을 호출하는 방식으로 만들어야 합니다. 
            이 이벤트가 <em>data</em> (POST 데이터의 새 청크가 도착했다)와 
            <em>end</em> (모든 청크를 다 받았다) 입니다.
        </p>

        <p>
            이 이벤트가 발생했을때 어떤 callback이 호출되어야 할지 Node.js 에게
            알려줘야 하는데, HTTP 요청이 올 때 <em>onRequest</em> 
            callback 함수가 넘겨받은 <em>request</em> 객체에 
            <em>listener</em> 함수들을 추가하는 방식으로 할 수 있습니다.
        </p>

        <p>
            기본적으로 이렇게 보일 겁니다:
        </p>
        <pre class="prettyprint lang-js"><span class="pln">request</span><span class="pun">.</span><span class="pln">addListener</span><span
                class="pun">(</span><span class="str">"data"</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">chunk</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="com">// called when a new chunk of data was received</span><span
                class="pln"><br></span><span class="pun">});</span><span class="pln"><br><br>request</span><span
                class="pun">.</span><span class="pln">addListener</span><span class="pun">(</span><span class="str">"end"</span><span
                class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span
                class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; </span><span
                class="com">// called when all chunks of data have been received</span><span
                class="pln"><br></span><span class="pun">});</span></pre>

        <p>
            이 로직을 어디에 구현해야 할까요? 지금은 server 에서만 request 객체에
            접근 가능합니다. router와 request handler 에는 <em>request</em> 
            객체를 전달하지 않았거든요. <em>response</em> 객체만 전달했었죠.
        </p>

        <p>
            제 생각에, request 로부터 오는 모든 data를 애플리케이션에게 
            전달하는 것은 HTTP server의 역할입니다. 
            그래서 POST data를 server에서 받고 최종 data를 router와 
            request handler로 보내는 게 좋겠습니다. 
            그러면 그것으로 무엇을 할지 결정할 수 있겠죠.
        </p>

        <p>
            그러니까 <em>data</em>와 <em>end</em> 이벤트 callback을 
            server에 두고 <em>data</em> callback에서 모든 POST 데이터 청크를 
            모은 다음에, <em>end</em> callback에서 router를 호출하면서 
            모든 데이터 청크를 전달합니다. 
            그러면 결국 request handler 까지 갈 겁니다.
        </p>

        <p>
            자 이제 <em>server.js</em> 부터 시작합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> postData </span><span class="pun">=</span><span
                class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; request</span><span
                class="pun">.</span><span class="pln">setEncoding</span><span class="pun">(</span><span class="str">"utf8"</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; request</span><span
                class="pun">.</span><span class="pln">addListener</span><span class="pun">(</span><span class="str">"data"</span><span
                class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span
                class="pun">(</span><span class="pln">postDataChunk</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; postData </span><span class="pun">+=</span><span class="pln"> postDataChunk</span><span
                class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Received POST data chunk '"</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; postDataChunk </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">"'."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">});</span><span
                class="pln"><br><br>&nbsp; &nbsp; request</span><span class="pun">.</span><span
                class="pln">addListener</span><span class="pun">(</span><span class="str">"end"</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span
                class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; route</span><span class="pun">(</span><span
                class="pln">handle</span><span class="pun">,</span><span class="pln"> pathname</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">});</span><span
                class="pln"><br><br>&nbsp; </span><span class="pun">}</span><span class="pln"><br><br>&nbsp; http</span><span
                class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            기본적으로 세 가지 일을 했습니다: 
            첫째, 받을 데이터의 인코딩을 UTF-8로 세팅했고, 
            새로운 POST 데이터 청크가 올 때마다 <em>postData</em> 변수에 
            차곡차곡 쌓는 역할을 하는 “data” 이벤트 listener를 추가했습니다. 
            그리고 모든 POST 데이터가 모였을 때 호출되는 <em>end</em> 이벤트 
            callback에서 postData 변수를 router로 전달했습니다. 
            POST 데이터도 router 전달했는데요, 
            request handler에서 필요하게 됩니다.
        </p>

        <p>
            제품 코드(production code)라면 청크가 올 때마다 콘솔 로그를 찍도록 
            하는 것은 안좋은 생각입니다만
            (POST 데이터가 수 메가 바이트가 될 수 있죠?),
            무슨 일이 벌어지는지 보는 것은 괜찮겠죠.
        </p>

        <p>
            이 부분에서 좀 살펴보는 것도 좋습니다. 
            textarea에 적은량의 텍스트를 넣다가 그 크기를 늘려가게 되면 
            <em>data</em> callback이 실제로 여러 번 호출됩니다.
        </p>

        <p>
            더 기막힌 걸 애플리케이션에 추가해 봅시다. 
            /upload 페이지에 받은 내용을 표시할 겁니다. 
            이렇게 하기 위해서는  <em>postData</em>를 request handler로 
            전달해야 합니다. 
            <em>router.js</em>를 아래와 같이 수정합니다.
        </p>

        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">handle</span><span class="pun">,</span><span
                class="pln"> pathname</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">if</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span
                class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span
                class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; handle</span><span
                class="pun">[</span><span class="pln">pathname</span><span class="pun">](</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">);</span><span class="pln"><br>&nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"No request handler found for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">404</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"404 Not found"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            그리고 <em>requestHandlers.js</em>의 <em>upload</em> 
            request handler에서 응답에 이 데이터를 추가합니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> start</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" content="text/html; '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'charset=UTF-8" /&gt;'</span><span class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" method="post"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;textarea name="text" rows="20" cols="60"&gt;&lt;/textarea&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Submit text" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/html&gt;'</span><span class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"You've sent: "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> postData</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br>exports</span><span class="pun">.</span><span class="pln">start </span><span
                class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            됐습니다. 이제 POST 데이터를 받아서 request handler에서 
            사용할 수 있습니다. 
        </p>

        <p>
            이 토픽의 마지막 할 일은 이렇습니다. 
            지금은 POST 요청의 전체 body를 router와 request handler로 
            넘기고 있는데, 
            향후에 POST 데이터를 구성하는 개별 필드를 사용하고 싶을 수 있습니다.
            이 경우에는 <em>text</em> 필드의 값이죠.
        </p>

        <p>
            우린 이미 <em>querystring</em> 모듈에 대해 알고 있죠. 
            이런식으로 사용하겠습니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> querystring </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"querystring"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" content="text/html; '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'charset=UTF-8" /&gt;'</span><span class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" method="post"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;textarea name="text" rows="20" cols="60"&gt;&lt;/textarea&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Submit text" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/html&gt;'</span><span class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"You've sent the text: "</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; querystring</span><span class="pun">.</span><span
                class="pln">parse</span><span class="pun">(</span><span class="pln">postData</span><span
                class="pun">).</span><span class="pln">text</span><span class="pun">);</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span></pre>

        <p>
            네. 초보자 튜토리얼에서 POST 데이터 처리에 대해 다룰 내용은 
            모두 다뤘습니다.
        </p>

        <a name="handling-file-uploads"></a>

        <h4>파일 업로드 처리하기</h4>

        <p>
            이제 마지막 유스케이스로 갑니다. 
            우리 계획은 사용자가 이미지 파일을 업로드 하면 업로드된 이미지를 
            브라우저에 출력하는 것이었습니다.
        </p>

        <p>
            90년대로 돌아간다면, 이 기능이 기업공개를 할만한 비즈니스 모델을 
            가능하게 해줄것 같습니다만, 
            오늘날에는 우리에게 두 가지를 가르쳐 줍니다. 
            Node.js 외부 library를 설치하는 방법과 
            이것을 코드에서 사용하는 방법이죠.
        </p>

        <p>
            우리가 사용할 외부 모듈은 Felix Geisendörfer가 만든 
            <em>node-formidable</em> 입니다. 
            이 모듈은 들어오는 파일 데이터를 파싱해서 처리하는 모든 자잘한 
            것들을 잘 추상화 해 놨습니다. 
            결국 파일 데이터를 받아서 처리하는 것은 단지 POST 데이터를 처리하는
            것입니다. 하지만 그 자세한 처리가 어렵고 복잡하기 때문에, 
            여기서는 미리 만들어진 솔루션을 쓰는 것이 좋겠습니다.
        </p>

        <p>
            Felix의 코드(모듈)을 사용하기 위해 적절한 모듈이 필요합니다. 
            Node.js는 <em>NPM</em>이라는 자체의 패키지 관리자를 가지고 있습니다.
            NPM은 Node.js 외부 모듈을 매우 쉽게 설치할 수 있게 해줍니다. 
            Node.js가 잘 동작하는 시스템이라면 단지 커맨드 라인에 아래와 같이 
            타이핑 하면 됩니다.
        </p>
        <pre class="prettyprint lang-bash"><span class="pln">npm install formidable</span></pre>

        <p>
            만약 아래와 같이 출력된다면 
        </p>
        <pre class="prettyprint lang-bash"><span class="pln">npm info build </span><span class="typ">Success</span><span
                class="pun">:</span><span class="pln"> formidable@1</span><span class="pun">.</span><span class="lit">0.9</span><span
                class="pln"><br>npm ok</span></pre>

        <p>
            잘 된 겁니다.
        </p>

        <p>
            이제 <em>formidable</em> 모듈을 코드에서 사용할 수 있습니다. 
            내부 모듈을 사용할 때 했던 것처럼 require만 해주면 됩니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> formidable </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"formidable"</span><span
                class="pun">);</span></pre>

        <p>
            formidable이 사용하는 은유는 HTTP POST로 submit 된 “form”을 
            Node.js에서 파싱할 수 있게 (“parseable”) 한다는 겁니다.  
            다음과 같이 사용하면 됩니다. 새 <em>IncomingForm</em>을 생성합니다.
            이것은 submit된 form의 추상화 객체인데 이것으로 <em>request</em>
            객체를 파싱하여 submit된 파일과 필드들을 얻을 수 있습니다.
        </p>

        <p>
            node-formidable 프로젝트 페이지에서 가져온 이 예제는 서로 다른 부분이
            어떻게 함께 동작하는지 잘 보여줍니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> formidable </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'formidable'</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; http </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">'http'</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; sys </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">'sys'</span><span
                class="pun">);</span><span class="pln"><br><br>http</span><span class="pun">.</span><span class="pln">createServer</span><span
                class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span
                class="pln"><br>&nbsp; </span><span class="kwd">if</span><span class="pln"> </span><span
                class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span
                class="pln">url </span><span class="pun">==</span><span class="pln"> </span><span
                class="str">'/upload'</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span
                class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span
                class="pun">.</span><span class="pln">toLowerCase</span><span class="pun">()</span><span
                class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'post'</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="com">// parse a file upload</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">var</span><span
                class="pln"> form </span><span class="pun">=</span><span class="pln"> </span><span
                class="kwd">new</span><span class="pln"> formidable</span><span class="pun">.</span><span class="typ">IncomingForm</span><span
                class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; form</span><span class="pun">.</span><span
                class="pln">parse</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">err</span><span class="pun">,</span><span class="pln"> fields</span><span
                class="pun">,</span><span class="pln"> files</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; res</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">'content-type'</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">'text/plain'</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; res</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">'received upload:\n\n'</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; res</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">(</span><span
                class="pln">sys</span><span class="pun">.</span><span class="pln">inspect</span><span
                class="pun">({</span><span class="pln">fields</span><span class="pun">:</span><span
                class="pln"> fields</span><span class="pun">,</span><span class="pln"> files</span><span
                class="pun">:</span><span class="pln"> files</span><span class="pun">}));</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">return</span><span
                class="pun">;</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span class="pln"><br><br>&nbsp; </span><span
                class="com">// show a file upload form</span><span class="pln"><br>&nbsp; res</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">'content-type'</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">'text/html'</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; res</span><span class="pun">.</span><span class="pln">end</span><span
                class="pun">(</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" enctype="multipart/form-data" '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'method="post"&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="text" name="title"&gt;&lt;br&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="file" name="upload" multiple="multiple"&gt;&lt;br&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Upload"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pln"><br>&nbsp; </span><span class="pun">);</span><span
                class="pln"><br></span><span class="pun">}).</span><span class="pln">listen</span><span
                class="pun">(</span><span class="lit">8888</span><span class="pun">);</span></pre>

        <p>
            이 코드를 파일에 추가하고 <em>node</em>를 통해 실행하면, 
            파일 업로드를 포함하는 단순한 form을 submit 할 수 있고, 
            <em>form.parse</em> 함수의 callback 에 파라미터로 넘어가는 
            <em>files</em> 객체가 어떻게 생겼는지 살펴볼 수 있습니다.
        </p>
        <pre class="lang-js">received upload:

{ fields: { title: 'Hello World' },
  files:
   { upload:
      { size: 1558,
        path: '/tmp/1c747974a27a6292743669e91f29350b',
        name: 'us-flag.png',
        type: 'image/png',
        lastModifiedDate: Tue, 21 Jun 2011 07:02:41 GMT,
        _writeStream: [Object],
        length: [Getter],
        filename: [Getter],
        mime: [Getter] } } }</pre>

        <p>
            우리 유스케이스대로 동작하게 하기 위해서 이 form 파싱 로직을 
            우리 코드에 넣어야 하고, 업로드된 파일 (<em>/tmp</em> 폴더에 
            저장될 겁니다)의 내용을 어떻게 브라우저에 보여줄지 
            방법을 찾아야 합니다.
        </p>

        <p>
            뒤에 것을 먼저 봅시다. 로컬 하드 드라이브에 이미지 파일이 있을 때 
            브라우저 요청에 어떻게 응답할 수 있을까요?
        </p>

        <p>
            당연히 이 파일의 내용을 Node.js server에서 읽어야 하는데요,
            역시, 이런일을 하는 모듈이 있습니다. <em>fs</em> 라는 모듈입니다.
        </p>

        <p>
            <em>/show</em> 라는 URL을 위한 또 하나의 request handler를 
            추가합시다. 
            이것은 <em>/tmp/test.png</em> 라는 파일의 내용을 뿌려줄 겁니다. 
            당연히 먼저 실제 png 이미지 파일을 이 위치에 저장해야겠죠.
        </p>

        <p>
            <em>requestHandlers.js</em>를 다음과 같이 수정합니다.
        </p>

        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> querystring </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"querystring"</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; fs </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"fs"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'content="text/html; charset=UTF-8" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" method="post"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;textarea name="text" rows="20" cols="60"&gt;&lt;/textarea&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Submit text" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/html&gt;'</span><span class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"You've sent the text: "</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; querystring</span><span class="pun">.</span><span
                class="pln">parse</span><span class="pun">(</span><span class="pln">postData</span><span
                class="pun">).</span><span class="pln">text</span><span class="pun">);</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> show</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'show' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; fs</span><span class="pun">.</span><span class="pln">readFile</span><span
                class="pun">(</span><span class="str">"/tmp/test.png"</span><span class="pun">,</span><span
                class="pln"> </span><span class="str">"binary"</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">error</span><span class="pun">,</span><span class="pln"> file</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">if</span><span class="pun">(</span><span class="pln">error</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">error </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">"\n"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"image/png"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">file</span><span
                class="pun">,</span><span class="pln"> </span><span class="str">"binary"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"><br>&nbsp; </span><span class="pun">});</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">show </span><span class="pun">=</span><span
                class="pln"> show</span><span class="pun">;</span></pre>

        <p>
            이 request handler를 <em>/show</em> 라는 URL 과 매핑해야겠죠. 
            <em>index.js</em>에서요.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> server </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"./server"</span><span
                class="pun">);</span><span class="pln"><br></span><span class="kwd">var</span><span
                class="pln"> router </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"./router"</span><span class="pun">);</span><span class="pln"><br></span><span class="kwd">var</span><span
                class="pln"> requestHandlers </span><span class="pun">=</span><span class="pln"> require</span><span
                class="pun">(</span><span class="str">"./requestHandlers"</span><span class="pun">);</span><span
                class="pln"><br><br></span><span class="kwd">var</span><span class="pln"> handle </span><span
                class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span
                class="pln"><br>handle</span><span class="pun">[</span><span class="str">"/"</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">;</span><span class="pln"><br>handle</span><span
                class="pun">[</span><span class="str">"/start"</span><span class="pun">]</span><span
                class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">;</span><span class="pln"><br>handle</span><span
                class="pun">[</span><span class="str">"/upload"</span><span class="pun">]</span><span
                class="pln"> </span><span class="pun">=</span><span class="pln"> requestHandlers</span><span
                class="pun">.</span><span class="pln">upload</span><span class="pun">;</span><span class="pln"><br>handle</span><span
                class="pun">[</span><span class="str">"/show"</span><span class="pun">]</span><span class="pln"> </span><span
                class="pun">=</span><span class="pln"> requestHandlers</span><span class="pun">.</span><span
                class="pln">show</span><span class="pun">;</span><span class="pln"><br><br>server</span><span
                class="pun">.</span><span class="pln">start</span><span class="pun">(</span><span
                class="pln">router</span><span class="pun">.</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">);</span></pre>

        <p>
            서버를 재시작하고 브라우저로 
            <a href="http://localhost:8888/show" rel="nofollow">http://localhost:8888/show</a>
           를 열면 <em>/tmp/test.png</em> 파일이 보여야 합니다.
        </p>

        <p>
            좋습니다. 이제 우리가 해야할 것은
        </p>
        
        <p>
            <ul>
                <li>
                    <em>/start</em>의 form 에 파일 업로드 element를 추가하고,
                </li>
                <li>
                    업로드된 파일을 <em>/tmp/test.png</em>에 저장하기 위해서 
                    node-formidable을 <em>upload</em> 
                    request handler 에 추가하고,
                </li>
        
                <li>
                    <em>/upload</em> URL의 출력 HTML 에 업로드된 
                    이미지를 추가합니다.
                </li>
            </ul>
        </p>

        <p>
            스텝 1은 단순하죠. HTML form의 encoding type 에 
            <em>multipart/form-data</em>를 추가하고, textarea는 삭제합니다. 
            파일 업로드 input 필드를 추가하고 submit 버튼의 텍스트를 
            “Upload file”이라고 바꿉니다. 이렇게 해 봅시다. 
            <em>requestHandlers.js</em> 파일입니다.
        </p>

        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> querystring </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"querystring"</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; fs </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"fs"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'content="text/html; charset=UTF-8" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" enctype="multipart/form-data" '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'method="post"&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;input type="file" name="upload"&gt;'</span><span class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;input type="submit" value="Upload file" /&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/form&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/body&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/html&gt;'</span><span
                class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> postData</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"You've sent the text: "</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; querystring</span><span class="pun">.</span><span
                class="pln">parse</span><span class="pun">(</span><span class="pln">postData</span><span
                class="pun">).</span><span class="pln">text</span><span class="pun">);</span><span class="pln"><br>&nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> show</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> postData</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'show' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; fs</span><span class="pun">.</span><span class="pln">readFile</span><span
                class="pun">(</span><span class="str">"/tmp/test.png"</span><span class="pun">,</span><span
                class="pln"> </span><span class="str">"binary"</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">error</span><span class="pun">,</span><span class="pln"> file</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">if</span><span class="pun">(</span><span class="pln">error</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">error </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">"\n"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"image/png"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">file</span><span
                class="pun">,</span><span class="pln"> </span><span class="str">"binary"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"><br>&nbsp; </span><span class="pun">});</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">show </span><span class="pun">=</span><span
                class="pln"> show</span><span class="pun">;</span></pre>

        <p>
            멋집니다. 다음 스텝은 조금 복잡합니다. 
            첫 번째 문제는, 파일 업로드를 <em>upload</em> request handler에서 
            처리하고 싶은데 이렇게 하려면 <em>request</em> 객체를 
            <em>form.parse</em> 함수에 넘겨줘야 합니다.
        </p>

        <p>
            하지만 우리에겐 <em>response</em> 객체와 <em>postData</em> 배열밖에
            없죠. 슬프게도 <em>request</em> 객체를 server에서 router 로, 
            또 request handler로 전달하고 다녀야 할 것 같습니다. 
            더 고상한 해결책이 있을 수도 있겠지만, 지금은 이렇게 해야겠네요.
        </p>

        <p>
            하는 김에, <em>postData</em> 관련 코드를 server와 request handler 
            에서 날려버립시다. 파일 업로드에 이런 코드가 필요하지 않을 뿐더러 
            다른 문제를 일으킬 수도 있어요.  
            이미 server에서 <em>request</em> 객체의 <em>data</em> 이벤트를 
            “소모했기” 때문에 <em>form.parse</em>에서도 이 이벤트를 받아야 
            하는데 더 이상 이 이벤트를 받을 수 없게 됩니다.
            (왜냐하면 Node.js는 어떤 data도 버퍼링 하지 않기 때문이죠)
        </p>

        <p>
            <em>server.js</em> 부터 시작해 봅시다. 
            postData 처리와 <em>request.setEncoding</em> 부분을 삭제합니다. 
            그리고 대신 <em>request</em>를 router로 넘깁니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
                class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
                class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
                class="pun">,</span><span class="pln"> handle</span><span class="pun">)</span><span class="pln"> </span><span
                class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="kwd">function</span><span
                class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
                class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
                class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
                class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; route</span><span class="pun">(</span><span
                class="pln">handle</span><span class="pun">,</span><span class="pln"> pathname</span><span
                class="pun">,</span><span class="pln"> response</span><span class="pun">,</span><span class="pln"> request</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
                class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
                class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
                class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
                class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span></pre>

        <p>
            다음으로 <em>router.js</em> 입니다. 
            postData를 넘기는 것은 더 이상 필요 없습니다. 
            대신 <em>request</em>를 넘기면 되죠.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
                class="pun">(</span><span class="pln">handle</span><span class="pun">,</span><span
                class="pln"> pathname</span><span class="pun">,</span><span class="pln"> response</span><span
                class="pun">,</span><span class="pln"> request</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; </span><span class="kwd">if</span><span
                class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span
                class="pln"> handle</span><span class="pun">[</span><span class="pln">pathname</span><span
                class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span
                class="pln"> </span><span class="str">'function'</span><span class="pun">)</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; handle</span><span
                class="pun">[</span><span class="pln">pathname</span><span class="pun">](</span><span class="pln">response</span><span
                class="pun">,</span><span class="pln"> request</span><span class="pun">);</span><span class="pln"><br>&nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"No request handler found for "</span><span
                class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">404</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/html"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="str">"404 Not found"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
                class="pln"> route</span><span class="pun">;</span></pre>

        <p>
            이제 <em>request</em> 객체를 <em>upload</em> request handler 
            함수에서 사용할 수 있게 되었습니다. 
            node-formidable 이 업로드되는 파일을 <em>/tmp</em>에 로컬파일로 
            잘 저장할 겁니다. 하지만 파일이 <em>/tmp/test.png</em>에 
            남아있는지는 우리 스스로 확인을 해 봅시다. 
            단순하게 유지하기 위해서 오직 PNG 이미지만 업로드 하는 것으로 
            가정합니다.
        </p>

        <p>
            이제 <em>fs.renameSync(path1, path2)</em>가 동작할 건데요, 
            이름이 암시하듯이 이것은 동기적으로 동작합니다. 
            따라서 만약 rename 동작이 비싸고 시간이 오래 걸린다면 
            blocking을 초래하겠죠. 
            우리는 모두 성인이고 우리가 뭘 하는지 알고 있다고 동의합시다.
        </p>

        <p>
            업로드된 파일을 관리하는 코드 몇줄과 rename 코드를 넣읍시다. 
            <em>requestHandler.js</em> 파일입니다.
        </p>
        <pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> querystring </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"querystring"</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; fs </span><span class="pun">=</span><span
                class="pln"> require</span><span class="pun">(</span><span class="str">"fs"</span><span
                class="pun">),</span><span class="pln"><br>&nbsp; &nbsp; formidable </span><span
                class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"formidable"</span><span
                class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> start</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'start' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;meta http-equiv="Content-Type" content="text/html; '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'charset=UTF-8" /&gt;'</span><span class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/head&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;form action="/upload" enctype="multipart/form-data" '</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'method="post"&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="file" name="upload" multiple="multiple"&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;input type="submit" value="Upload file" /&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/form&gt;'</span><span class="pun">+</span><span
                class="pln"><br>&nbsp; &nbsp; </span><span class="str">'&lt;/body&gt;'</span><span
                class="pun">+</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="str">'&lt;/html&gt;'</span><span class="pun">;</span><span class="pln"><br><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/html"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">body</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br></span><span
                class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> upload</span><span
                class="pun">(</span><span class="pln">response</span><span class="pun">,</span><span class="pln"> request</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'upload' was called."</span><span
                class="pun">);</span><span class="pln"><br><br>&nbsp; </span><span class="kwd">var</span><span
                class="pln"> form </span><span class="pun">=</span><span class="pln"> </span><span
                class="kwd">new</span><span class="pln"> formidable</span><span class="pun">.</span><span class="typ">IncomingForm</span><span
                class="pun">();</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span
                class="pln">log</span><span class="pun">(</span><span class="str">"about to parse"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; form</span><span class="pun">.</span><span
                class="pln">parse</span><span class="pun">(</span><span class="pln">request</span><span
                class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span
                class="pun">(</span><span class="pln">error</span><span class="pun">,</span><span
                class="pln"> fields</span><span class="pun">,</span><span class="pln"> files</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"parsing done"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; fs</span><span class="pun">.</span><span
                class="pln">renameSync</span><span class="pun">(</span><span class="pln">files</span><span
                class="pun">.</span><span class="pln">upload</span><span class="pun">.</span><span
                class="pln">path</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/tmp/test.png"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
                class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
                class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/html"</span><span
                class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span
                class="str">"received image:&lt;br/&gt;"</span><span class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"&lt;img src='/show' /&gt;"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">});</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span
                class="pln"> show</span><span class="pun">(</span><span class="pln">response</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
                class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request handler 'show' was called."</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; fs</span><span class="pun">.</span><span class="pln">readFile</span><span
                class="pun">(</span><span class="str">"/tmp/test.png"</span><span class="pun">,</span><span
                class="pln"> </span><span class="str">"binary"</span><span class="pun">,</span><span
                class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span
                class="pln">error</span><span class="pun">,</span><span class="pln"> file</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="kwd">if</span><span class="pun">(</span><span class="pln">error</span><span
                class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">error </span><span
                class="pun">+</span><span class="pln"> </span><span class="str">"\n"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span
                class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
                class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
                class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
                class="pln"> </span><span class="str">"image/png"</span><span class="pun">});</span><span
                class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span class="pun">.</span><span
                class="pln">write</span><span class="pun">(</span><span class="pln">file</span><span
                class="pun">,</span><span class="pln"> </span><span class="str">"binary"</span><span
                class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; response</span><span
                class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; &nbsp; </span><span
                class="pun">}</span><span class="pln"><br>&nbsp; </span><span class="pun">});</span><span
                class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
                class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
                class="pln"> start</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">upload </span><span class="pun">=</span><span
                class="pln"> upload</span><span class="pun">;</span><span class="pln"><br>exports</span><span
                class="pun">.</span><span class="pln">show </span><span class="pun">=</span><span
                class="pln"> show</span><span class="pun">;</span></pre>

        <p>
            자 다 됐습니다. 서버를 재시작 하고 유스케이스가 완전히 잘 동작합니다.
            로컬 하드 드라이브에 있는 PNG 이미지를 선택하고, 
            서버에 업로드하고, 웹페이지에 출력됩니다.
        </p>

        <a name="conclusion-and-outlook"></a>

        <h2>결론과 개관</h2>

        <p>
            축하합니다. 우리의 미션을 달성했습니다. 
            우리는 단순하지만 제대로 된 Node.js 웹 애플리케이션을 작성했습니다.
            우리는 서버 사이드 JavaScript, 함수형 프로그래밍, 
            blocking 과 non-blocking 동작, callback, 이벤트, custom, 
            내부, 외부 모듈 그 외에 여러 가지에 대해 이야기 했습니다.
        </p>

        <p>
            물론 우리가 다루지 않은 많은 내용들이 있습니다. 
            데이터베이스와 어떻게 통신하는지, 유닛 테스트를 어떻게 작성하는지, 
            NPM을 통해 설치할 수 있는 외부 모듈을 어떻게 만드는지, 
            GET 요청을 어떻게 다루는지와 같은 단순한 것들도 있지요.
        </p>

        <p>
            하지만 그것은 초보자를 대상으로한 모든 책들의 운명입니다.
            모든 내용을 자세히 다룰 수는 없죠.
        </p>

        <p>
            좋은 소식은 Node.js 커뮤니티가 매우 활발하다는
            (카페인을 먹은 ADHD-과잉운동성장애 아이를 긍정적으로 상상해보세요) 
            것입니다. 이것은 자료와, 당신이 질문할 곳이 많다는 의미입니다. 
            더 많은 정보를 위해서는 아마 
            <a href="https://github.com/joyent/node/wiki">Node.js community wiki</a>와 
            <a href="http://www.nodecloud.org/">the NodeCloud directory</a> 가
            가장 좋은 시작 지점이 될 겁니다.
        </p>
        </div>

        <div class="buy-the-bundle">
            <div class="cover">
                <p>
                    The perfect introduction plus the perfect reference in one bundle!
                </p>
                <a href="/buy-bundle-bottom/"><img src="the_node_beginner_book_cover.png" height="86" width="57" /></a>
                <a href="/buy-bundle-bottom/"><img src="hands-on_node.js_cover.png" height="86" width="57" /></a>
            </div>
            <div class="description">
                <p>
                    LeanBundle currently offers<br />
                    the final version of
                    <br />
                    <strong>The Node Beginner Book</strong>
                    <br />
                    plus Pedro Teixeira's excellent
                    <br />
                    <strong>Hands-on Node.js</strong> for only
                    <br />
                    <br />
                    <strong class="price dollarsign">$</strong><strong class="price">9.99</strong>
                    <br />
                    (regular price <del>$21.98</del>)
                </p>
            </div>
            <div class="buy">
                <p>
                    226 pages in total
                    <br />
                    PDF, ePub & MOBI
                    <br />
                    Direct download
                    <br />
                    Free updates
                </p>
                <a class="buttonlink" href="/buy-bundle-bottom/">
                    <div class="button">Buy this<br />bundle now</div>
                </a>
            </div>
        </div>

        <div id="praise">
            <div class="praise">
                <div class="comment">
                    "This is an amazing introduction to Node."
                </div>
                <div class="author">
                    Ryan Dahl, creator of Node.js
                </div>
            </div>
            <div class="praise">
                <div class="comment">
                    "I love nodebeginner.org - concise, direct to the point and
                    even enjoyable to read."
                </div>
                <div class="author">Gojko Adzic, author of <em>Specification by Example</em> and <em>Bridging the Communication Gap</em></div>
            </div>
            <div class="praise">
                <div class="comment">
                    "This is one of the best tutorials I've read.
                    As a former Java coder, I've always found JavaScript
                    to be a black art, but you have really simplified
                    things with this tutorial."
                </div>
                <div class="author">Erskine, from the comments</div>
            </div>
            <div class="praise">
                <div class="comment">
                    "This is one of the few beginner articles I made it all the
                    way through because of how well it's written."
                </div>
                <div class="author">
                    Paul Gibler, from the comments
                </div>
            </div>
            <div class="praise">
                <div class="comment">
                    "Indispensable."
                </div>
                <div class="author">
                    @lecolibrilibre, on Twitter
                </div>
            </div>
            <div class="praise">
                <div class="comment">
                    "I just wanted to drop you a note to say thank you for
                    writing such an excellent introduction to node. Your book's
                    explanation is fantastic, and I can't wait for you to
                    finish it!"
                </div>
                <div class="author">
                    Seth McLaughlin, via eMail
                </div>
            </div>
        </div>

        <div id="disqus_thread"></div>

        <div id="footer">
            <p id="ccimage">
                <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img alt="Creative Commons License" border="0" src="creative_commons.png" width="88" height="31"/></a>
            </p>
            <p>
                <span xmlns:dct="http://purl.org/dc/terms/">The Node Beginner Book</span>
                by
                <a xmlns:cc="http://creativecommons.org/ns#" href="http://manuel.kiessling.net" rel="cc:attributionURL">Manuel Kiessling</a> (see <a href="https://plus.google.com/100272082905360445612?rel=author">Google+ profile</a>)
                is licensed under a
                <br />
                <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License</a>.
                <br />
                Permissions beyond the scope of this license may be available at <a xmlns:cc="http://creativecommons.org/ns#" href="mailto:manuel@kiessling.net" rel="cc:morePermissions">manuel@kiessling.net</a>.
            </p>
        </div>
    </body>
</html>
